#!/bin/bash
# 获取lnlamp脚本所在的目录
lnlamp_dir=$(cd `dirname $0`; pwd)
# echo "lnlamp所在的路径是:" $lnlamp_dir
# 获取执行脚本时所在的目录
Rootpath=`pwd`
# echo "当前的工作路径是:" $Rootpath
cd $Rootpath



# 如果没有输入参数,直接退出,并提示用户lnlamp的用法
if [ $# -eq 0 ];
then
    echo "Usage:   lnlamp <c_source_file> [options...]";
    echo "Example: lnlamp hello.c";
    echo "Note:    For detailed usage, please see 'lnlamp -h' ";
    exit 1;
fi;
# 如果捕获到CTRL+C,则直接退出
trap "onCtrlC" SIGINT
function onCtrlC () {
    rm -f ____lnlamp_*
    exit
}
# 将堆栈的大小设置为无限制
ulimit -s unlimited


# 调试模式开关
DEBUG_TYPE=1
# TODO: set polybench test switch 
POLYBENCH_TEST_SWITCH=1
# TODO: 添加计时方式 (-t|--timing-type) 的设置
timing_type=0
# TODO: 添加profiling时的输入文件 (-i|--input) 的设置
input="input.txt"
# TODO: 完善下面 Profiling时编译的一些参数的自定义设置(CC已经实现根据后缀名字自动确定)
VERBOSE=""
CC="/home/sheen/llvm-project/llvm-install/bin/clang"
CFLAGS="-O3"
LIB_FLAGS="-I. -I/home/sheen/lnlamp/polybench_benchmark/utilities /home/sheen/lnlamp/polybench_benchmark/utilities/polybench.c"
PROFILER_FLAGS="-DPOLYBENCH_TIME -DPOLYBENCH_DUMP_ARRAYS -DPOLYBENCH_STACK_ARRAYS"
EXIT_FLAGS="-lm"


# 源文件参数
src_args=()
# 参数计数器
parameter_count=0
# 是否指定target_file的Flags
specify_output_flag=0
target_file=""
# 是否指定rate_array的Flag
specify_rate_array_flag=0
rate_array=(0 12 25 37 50 62 75 87 99)
start_rate=0
end_rate=99
# 是否指定tile的Flags
specify_tile_flag=0
tile_size=""
PPCG_TILE_FLAGS=""
# 是否指定openmp的Flags(默认线程数为4)
specify_openmp_flag=0
openmp_nums=""
PPCG_OPENMP_FLAGS=""
num_threads=4
if [ "$PPCG_OPENMP_FLAGS" = "--openmp" ];
then
    CFLAGS="$CFLAGS -fopenmp"
fi
# 是否指定schedule的Flags
specify_sched_flags=0
sched_algo=""
PPCG_SCHEDULE_FLAGS=""
# 是否指定ISL库的Flags
specify_isl_flags=0
isl_flags=""
PPCG_ISL_FLAGS=""
# c++ Flags
cpp_flag=0
# 临时profiling的后缀
prf_suf=""
# Profiling的次数(不包含数据预热）,必须为10，暂不支持修改
frequency=10
readonly frequency
# TODO: 这里还差两个配置参数的自定义支持
# Maximal variance accepted between the 10 median runs for performance results.
VARIANCE_ACCEPTED=20;
# 设定误差阈值,及其类型(1-最大绝对误差(默认)，2-最大相对误差，3-平均绝对误差，4-平均相对误差)
ERROR_TYPE=1
# 是否指定error_threshold的Flags
specify_error_threshold_flags=0
err_thr=""
ERROR_THRESHOLD=99999999999999999999

# Step0: 先处理一下输入.
while [[ $# -gt 0 ]];
do
    # 处理输入的参数
    case $1 in
        *.c|*.cc|*.cpp)
            parameter_count=`expr $parameter_count + 1`
            if [ $specify_output_flag -eq 1 ];
            then
                target_file=$1
                # 指定完target-file,则flag设为2.
                specify_output_flag=2
                shift
            else
                if [ -e $1 ];
                then
                    echo "YES" > /dev/null
                else
                    echo "lnlamp: error: $1 : No such file or directory"
                    echo "lnlamp: fatal error: no input files"
                    echo "Compilation terminated."
                    echo ""
                    echo "Please use option '-h | --help' to quickly use lnlamp."
                    echo ""
                    exit
                fi
                src_args+=("$1")
                shift
            fi
            ;;
        -s|--specify-output)
            parameter_count=`expr $parameter_count + 1`
            if [ $parameter_count -eq 1 ]
            then
                echo ""
                echo "Please put source file before option '-s'"
                echo ""
                echo "Template:"
                echo "    lnlamp <source-file> -s <target-file>"
                echo ""
                echo "    if <target-file> is empty, output 'source_lnlamp.c' or 'source_lnlamp.cpp' by default"
                echo ""	
                exit
            fi
            # 如果需要指定target-file,则flag设为1
            specify_output_flag=1
            shift
            ;;
        -r|--rate-array)
            parameter_count=`expr $parameter_count + 1`
            # 如果需要指定rate_array,则flag设为1
            specify_rate_array_flag=1
            shift
            ;;
        -t|--tile)
            parameter_count=`expr $parameter_count + 1`
            # 如果需要指定循环分块,则flag设为1
            specify_tile_flag=1
            shift
            ;;
        -a|--sched-algo)
            parameter_count=`expr $parameter_count + 1`
            # 如果指定了调度变换算法,则flag设为1
            specify_sched_flags=1
            shift
            ;;
        -i|--isl-flags)
            parameter_count=`expr $parameter_count + 1`
            # 如果指定了isl的Flags,则flag设为1
            specify_isl_flags=1
            shift
            ;;
        -v|--version)
            parameter_count=`expr $parameter_count + 1`
            echo "The installation position is: $lnlamp_dir"
            echo "Profiling  Configuration  is: ${VERBOSE} ${CC} ${CFLAGS} ${LIB_FLAGS} ${PROFILER_FLAGS} source_file ${EXIT_FLAGS}"
            echo
            echo "The lnlamp version is 0.1.0"
            echo "For more information, please see https://github.com/sheenisme/lnlamp.git"
            shift
            exit
            ;;
        -h|--help)
            parameter_count=`expr $parameter_count + 1`
            echo ""
            echo "Usage: lnlamp file [options] ..."
            echo ""
            echo "Options:"
            echo "    -s | --specify-output    specify the target file"
            echo "    -r | --rate-array        specify the rate-array of profiling(default is:$(echo ${rate_array[*]}))"
            echo "    -e | --error-threshold   specify the error-threshold(default is:$ERROR_THRESHOLD)"
            echo "    -v | --version           lnlamp version"
            echo "    -t | --tile              lnlamp specify the tile-sizes(default none) in PPCG"
            echo "    -o | --openmp            lnlamp specify uses the --openmp in PPCG, and multi-threads(default is:$num_threads) running."
            echo "    -a | --sched-algo        lnlamp specify the schedule-algorithm to isl|feautrier|no in PPCG, default is isl"
            echo "    -i | --isl-flags         lnlamp specify the flags in isl library of PPCG, default is null"
            echo ""
            echo "Examples:"
            echo "    lnlamp hello.c -s hello_lnlamp.c"
            echo ""
            echo "Template:"
            echo "    lnlamp <source-file> [Options] <target-file>"
            echo ""
            echo "Looking forward to more options ..."
            echo ""
            shift
            exit
            ;;
        -e|--error-threshold)
            parameter_count=`expr $parameter_count + 1`
            # 如果指定了error-threshold的Flags,则flag设为1
            specify_error_threshold_flags=1
            shift
            ;;
        -o|--openmp)
            parameter_count=`expr $parameter_count + 1`
            # 如果指定了openmp的Flags,则flag设为1
            specify_openmp_flag=1
            shift
            ;;
        *)
            parameter_count=`expr $parameter_count + 1`
            if [ $specify_output_flag -eq 1 ];
            then
                src_args+=("$1")
                target_file=$1
                specify_output_flag=2
                shift
            elif [ $specify_rate_array_flag -eq 1 ];
            then
                temp_rate_array=$1
                specify_rate_array_flag=2
                shift
            elif [ $specify_tile_flag -eq 1 ];
            then
                tile_size=$1
                specify_tile_flag=2
                shift
            elif [ $specify_sched_flags -eq 1 ];
            then
                sched_algo=$1
                specify_sched_flags=2
                shift
            elif [ $specify_isl_flags -eq 1 ];
            then
                isl_flags=$1
                specify_isl_flags=2
                shift
            elif [ $specify_error_threshold_flags -eq 1 ];
            then
                err_thr=$1
                specify_error_threshold_flags=2
                shift
            elif [ $specify_openmp_flag -eq 1 ];
            then
                openmp_nums=$1
                specify_openmp_flag=2
                shift
            else
                echo ""
                echo "Sorry, the '$1' operation is invalid!"
                echo ""
                echo "Please use option '-h | --help' to quickly use lnlamp"
                echo ""
                shift
                exit   
            fi
    esac
done
# 检查src_args长度是否为1,目前暂只支持一个源文件的自动混合精度
if [ ${#src_args[@]} -ne 1 ];
then
    echo "lnlamp: error: Parameter input error"
    echo "lnlamp: fatal error: input files is not 1(${#src_args[@]}) "
    echo "Compilation terminated."
    echo ""
    echo "Please use option '-h | --help' to quickly use lnlamp."
    echo ""
    exit
fi
PARAMETER_READY=true
# 输入参数的处理over,下面再处理一下其他的一些参数.

# 设置target_file
if [ $specify_output_flag -le 1 ];
then
    # 如果设置了'-s',但是没有设置'target_file',则进行警告
    if [ $specify_output_flag -eq 1 ];
    then
        echo "lnlamp: warning: missing target-file name after '-s', taregt-file will be reset to <source>_lnlamp.c or <source>_lnlamp.cpp"
    fi
    for src in ${src_args[@]}; 
    do  
        kernel=${src##*/}
        kernel=${kernel%%.*}
        target_file="${kernel}_lnlamp.c"
    done
fi

# 设置rate_array
if [ $specify_rate_array_flag -ge 1 ];
then
    # 如果设置了'-r',但是没有设置'rate_array',则进行警告
    if [ $specify_rate_array_flag -eq 1 ];
    then
        echo "lnlamp: warning: missing rate-array string after '-r', rate-array will be reset to $(echo ${rate_array[*]})."
    else
        rate_array=(${temp_rate_array[@]})
    fi
fi

# 自动判断后缀类型
for src in ${src_args[@]}; 
do
    case $src in
        *.c)
            echo "c files " > /dev/null
            cpp_flag=0
            CC+=" "
            prf_suf=".c"
            ;;
        *.cc)
            echo "c++ files " > /dev/null
            cpp_flag=1
            CC+="++ "
            target_file="${target_file}c"
            prf_suf=".cc"
            ;;
        *.cpp)
            echo "c++ files " > /dev/null
            cpp_flag=2
            CC+="++ "
            target_file="${target_file}pp"
            prf_suf=".cpp"
            ;;
        *)
            echo "lnlamp: warning: unsupported file suffixes, please note. "
    esac      
done

# 设置循环分块及其大小
if [ $specify_tile_flag -ge 1 ];
then
    # 如果设置了'-t',但是没有设置'tile-size',则进行警告
    if [ $specify_tile_flag -eq 1 ];
    then
        echo "lnlamp: warning: Missing tile size string after '-t', tile size be reset to '32' "
        PPCG_TILE_FLAGS="--tile --tile-size=32"
    else
        case "${tile_size}" in 
            [1-9][0-9]*)  
                PPCG_TILE_FLAGS="--tile --tile-size=${tile_size}"
                ;; 
            *)
                PPCG_TILE_FLAGS="--split-tile --tile-sizes=${tile_size}"
                ;; 
        esac
    fi
fi

# 设置多线程及其数量
if [ $specify_openmp_flag -ge 1 ];
then
    # 更新PPCG和编译器的FLAGS
    PPCG_OPENMP_FLAGS="--openmp"
    if [ "$PPCG_OPENMP_FLAGS" = "--openmp" ];
    then
        CFLAGS="$CFLAGS -fopenmp"
    fi

    # 如果设置了'-o',但是没有设置'num-threads',则进行警告
    if [ $specify_openmp_flag -eq 1 ];
    then
        echo "lnlamp: warning: Missing the number of multi-threads after '-o', number of multi-threads be reset to $num_threads "
    else
        num_threads=(${openmp_nums})
    fi
fi

# 设置PPCG的调度变换算法
if [ $specify_sched_flags -ge 1 ];
then
    # 如果设置了'-a',但是没有设置'sched-algo'的具体值,则进行警告
    if [ $specify_sched_flags -eq 1 ];
    then
        echo "lnlamp: warning: Missing schedule-algorithm string after '-a', so the --isl-schedule-algorithm will be reset to 'isl'. "
        PPCG_SCHEDULE_FLAGS+=""
    else
        case "${sched_algo}" in 
            *isl*)  
                PPCG_SCHEDULE_FLAGS+=""    # 默认便是isl调度变换算法
                ;;
            *feautrier*)  
                PPCG_SCHEDULE_FLAGS+="--isl-schedule-algorithm=feautrier"    # 需要手工指定才能修改为feautrier
                ;; 
            *no*)
                PPCG_SCHEDULE_FLAGS+="--no-reschedule"    # 需要手工设置no-reschedudle
                PPCG_TILE_FLAGS=""        # 不进行调度变换,那么就没必要进行循环分块和OPENMP参数的设定了
                PPCG_OPENMP_FLAGS=""
                ;;
            *)
                echo "lnlamp: warning: the schedule-algorithm string after '-a' is Non-legitimate(isl|feautrier|no), so the --isl-schedule-algorithm will be reset to 'isl'. "
                PPCG_SCHEDULE_FLAGS+=""
        esac
    fi
fi

# 设置ISL库的FLAGS
if [ $specify_isl_flags -ge 1 ];
then
    # 如果设置了'-i',但是没有设置'isl_flags',则进行警告
    if [ $specify_isl_flags -eq 1 ];
    then
        echo "lnlamp: warning: Missing isl flags after '-i', the flags will be reset null."
        PPCG_ISL_FLAGS+=""
    else
        PPCG_ISL_FLAGS+="${isl_flags}"
    fi
fi

# 设置error-threshold
if [ $specify_error_threshold_flags -ge 1 ];
then
    # 如果设置了'-e',但是没有设置'error-threshold',则进行警告
    if [ $specify_error_threshold_flags -eq 1 ];
    then
        echo "lnlamp: warning: missing error-threshold string after '-e', the error-threshold will be reset to $ERROR_THRESHOLD."
    else
        ERROR_THRESHOLD=(${err_thr})
    fi
fi
# 释放flag变量
unset specify_output_flag
unset specify_tile_flag
unset specify_openmp_flag
unset specify_sched_flags
unset specify_isl_flags
unset specify_error_threshold_flags



# Step1: 先计算double和float的误差情况.
# 使用 date +%s%N 可以获得一个纳秒级的unix时间戳(当前时间), 进行计时
start=`date +%s%N`
if [[ ${PARAMETER_READY} = true ]]; then
    # 如果用户没有指定rate_array，则用误差数据去确定;如果指定了，那么直接去Profiling.
    if [ $specify_rate_array_flag -le 1 ];
    then
        # 并行地编译Double和Float精度计算的代码
        {
            ppcg --target c --no-automatic-mixed-precision ${PPCG_ISL_FLAGS} ${PPCG_SCHEDULE_FLAGS} ${PPCG_TILE_FLAGS} ${PPCG_OPENMP_FLAGS} $src_args -o ____lnlamp_ppcg__${prf_suf} > /dev/null 2>&1
            if [ $? -ne 0 ]; then
                echo "lnlamp: error: PPCG Codegen meets errors."
                echo "lnlamp: error: The PPCG CMD is : ppcg --target c --no-automatic-mixed-precision ${PPCG_ISL_FLAGS} ${PPCG_SCHEDULE_FLAGS} ${PPCG_TILE_FLAGS} ${PPCG_OPENMP_FLAGS} $src_args -o ____lnlamp_ppcg__${prf_suf} "
                exit
            fi
            ${VERBOSE} ${CC} ${CFLAGS} ${LIB_FLAGS} ${PROFILER_FLAGS} ____lnlamp_ppcg__${prf_suf} -o  ____lnlamp_ppcg_double__.exe ${EXIT_FLAGS} > /dev/null 2>&1
            if [ $? -ne 0 ]; then
                echo "lnlamp: error: Compiling meets errors."
                echo "lnlamp: error: The compiler CMD is : ${VERBOSE} ${CC} ${CFLAGS} ${LIB_FLAGS} ${PROFILER_FLAGS} -DDATA_TYPE_IS_DOUBLE=1 ____lnlamp_ppcg__${prf_suf} -o  ____lnlamp_ppcg_double__.exe ${EXIT_FLAGS}"
                exit
            fi
            rm -f ____lnlamp_ppcg__${prf_suf}
        }&
        {
            ppcg --target c -R $start_rate ${PPCG_ISL_FLAGS} ${PPCG_SCHEDULE_FLAGS} ${PPCG_TILE_FLAGS} ${PPCG_OPENMP_FLAGS} $src_args -o ____lnlamp_amp__${prf_suf} > /dev/null 2>&1
            if [ $? -ne 0 ]; then
                echo "lnlamp: error: PPCG Codegen meets errors."
                echo "lnlamp: error: The PPCG CMD is : ppcg --target c -R ${rate_array[0]} ${PPCG_ISL_FLAGS} ${PPCG_SCHEDULE_FLAGS} ${PPCG_TILE_FLAGS} ${PPCG_OPENMP_FLAGS} $src_args -o ____lnlamp_${rate_array[0]}__${prf_suf} "
                exit
            fi
            ${VERBOSE} ${CC} ${CFLAGS} ${LIB_FLAGS} ${PROFILER_FLAGS} ____lnlamp_amp__${prf_suf} -o  ____lnlamp_ppcg_float__.exe ${EXIT_FLAGS} > /dev/null 2>&1
            if [ $? -ne 0 ]; then
                echo "lnlamp: error: Compiling meets errors."
                echo "lnlamp: error: The compiler CMD is : ${VERBOSE} ${CC} ${CFLAGS} ${LIB_FLAGS} ${PROFILER_FLAGS} -DDATA_TYPE_IS_FLOAT=1  ____lnlamp_ppcg__${prf_suf} -o  ____lnlamp_ppcg_float__.exe ${EXIT_FLAGS}"
                exit
            fi
            rm -f ____lnlamp_amp__${prf_suf}
        }&
        wait
        
        
        # 执行程序，获取计算结果
        if [ -e $input ];
        then
            { ./____lnlamp_ppcg_double__.exe < $input 2> ____lnlamp_error_double.res > /dev/null; } 2> /dev/null
            { ./____lnlamp_ppcg_float__.exe  < $input 2> ____lnlamp_error_float.res  > /dev/null; } 2> /dev/null
        else
            { ./____lnlamp_ppcg_double__.exe  2> ____lnlamp_error_double.res > /dev/null; } 2> /dev/null
            { ./____lnlamp_ppcg_float__.exe   2> ____lnlamp_error_float.res  > /dev/null; } 2> /dev/null
        fi
        rm -f ____lnlamp_ppcg_double__.exe ____lnlamp_ppcg_float__.exe

        # 删除非计算结果的那些字符串
        sed -i "/==BEGIN DUMP_ARRAYS==/d"  ____lnlamp_error_double.res
        sed -i "/==END   DUMP_ARRAYS==/d"  ____lnlamp_error_double.res
        sed -i "/begin dump/d"             ____lnlamp_error_double.res 
        sed -i "/end   dump/d"             ____lnlamp_error_double.res
        sed -i "/==BEGIN DUMP_ARRAYS==/d"  ____lnlamp_error_float.res
        sed -i "/==END   DUMP_ARRAYS==/d"  ____lnlamp_error_float.res
        sed -i "/begin dump/d"             ____lnlamp_error_float.res 
        sed -i "/end   dump/d"             ____lnlamp_error_float.res
        # 计算误差结果
        python3 $lnlamp_dir/lnlamp_internal_calculate_errors.py ____lnlamp_error_double.res ____lnlamp_error_float.res > lnlamp_internal_usage.py.log 2>&1 ;
        if [ $? -ne 0 ]; then
            echo "lnlamp: error: Calculate errors(lnlamp_internal_calculate_errors.py) problems encountered!"
            exit
        fi
        rm -f ____lnlamp_error_float.res

        # 获取各种误差数据
        double_no=`cat lnlamp_internal_usage.py.log | head -n 1`;
        float_no=` cat lnlamp_internal_usage.py.log | head -n 2 | tail -n 1`;
        mean_err_prc=`cat lnlamp_internal_usage.py.log | head -n 3 | tail -n 1`;
        mean_err_abs=`cat lnlamp_internal_usage.py.log | head -n 4 | tail -n 1`;
        max_err_prc=`cat lnlamp_internal_usage.py.log | head -n 5 | tail -n 1`;
        max_err_abs=`cat lnlamp_internal_usage.py.log | head -n 6 | tail -n 1`;

        # 确定单调下降的误差曲线在0和99处的误差值
        # 如果有非数，先不进行处理
        if [ $ERROR_TYPE -eq 1 ]; then
            max_err=$max_err_abs
            min_err=0.0
        elif [ $ERROR_TYPE -eq 2 ]; then
            max_err=$max_err_prc
            min_err=0.0
        elif [ $ERROR_TYPE -eq 3 ]; then
            max_err=$mean_err_abs
            min_err=0.0
        elif [ $ERROR_TYPE -eq 4 ]; then
            max_err=$mean_err_prc
            min_err=0.0
        else
            echo "lnlamp: error: ERROR_TYPE configuration errors!"
            exit
        fi
        unset double_no
        unset float_no
        unset mean_err_prc
        unset mean_err_abs
        unset max_err_prc
        unset max_err_abs
        
        # 如果误差阈值小于当前大于最小误差，那么说明配置有误
        if [ $(echo "$ERROR_THRESHOLD < $min_err" | bc) -eq 1 ];
        then
            echo "lnlamp: error: ERROR THRESHOLD configuration errors: expr ($ERROR_THRESHOLD > $min_err) is wrong!"
            exit
        # 如果误差阈值小于当前最大误差,大于最小误差,那么修改start_rate、end_rate以及rate_array.
        elif [ $(echo "$ERROR_THRESHOLD < $max_err" | bc) -eq 1 ];
        then
            new_start=$(echo $max_err $min_err $ERROR_THRESHOLD $end_rate $start_rate | awk '{ printf("%d", ($1-$3)/($1-$2)*($4-$5)+$5 +1); }'); # 最后的加1表示向上取值
            # echo "max:" $max_err "min:" $min_err "threshold:" $ERROR_THRESHOLD "end:" $end_rate "start:" $start_rate "new start:" $new_start;
            start_rate=$new_start;
            length_rate=`expr $end_rate \- $start_rate`;
            if [ $length_rate -lt 8 ]; then
                echo "lnlamp: The mixed-precision configurations cannot be found within the specified error threshold($ERROR_THRESHOLD, because the lower precision max error is $max_err)!"
                exit;
            else
                stride=`expr $length_rate \/ 8`;
            fi
            unset rate_array
            rate_array=()
            rate_array+=($start_rate);
            for ((i=1;i<8;i++))
            do
                temp=`expr $i \* $stride \+ $start_rate`;
                rate_array+=($temp); 
            done
            rate_array+=($end_rate);
            # echo "start:" $start_rate ",length:" $length_rate ",stride:" $stride ",rate range:"$(echo ${rate_array[*]}) ".";
        # 如果都不是以上两种情况，说明误差阈值大于当前最大误差，[0,99]的比例都是可以的，那么保持默认的配置
        fi
        
        if [ $DEBUG_TYPE -eq 1 ]; then
            echo "lnlamp: message: The Best fit range is: [$start_rate, $end_rate], when ERROR THRESHOLD is $ERROR_THRESHOLD, the ERROR TYPE is $ERROR_TYPE (the type max-err is $max_err). "
        fi
    fi
    ERROR_READY=true
fi
end=`date +%s%N`
time_error=$((($end-$start)/1000000)) # 毫秒



#  Step2: 如果输入解析成功,那么开始进行Profiling
# 使用 date +%s%N 可以获得一个纳秒级的unix时间戳(当前时间), 进行计时
start=`date +%s%N`
# 计算执行时间的方差函数,这一步要多次调用到
compute_mean_exec_time()
{
    file="$1";
    benchcomputed="$2";
    # 去掉$2中的'/'左边的字符，'.'右边的字符
    str=${2##*/};
    str=${str%%.*};

    cat "$file" > avg_${str}.out;
    expr="(0";
    while read n; do
	expr="$expr+$n";
    done < avg_${str}.out;
    time=`echo "scale=10;$expr)/10" | bc`;
    tmp=`echo "$time" | cut -d '.' -f 1`;
    if [ -z "$tmp" ]; then
	time="0$time";
    fi;
    # 拿到10份中间的数据结果
    val1=`cat avg_${str}.out | head -n 1`;
    val2=`cat avg_${str}.out | head -n 2 | tail -n 1`;
    val3=`cat avg_${str}.out | head -n 3 | tail -n 1`;
    val4=`cat avg_${str}.out | head -n 4 | tail -n 1`;
    val5=`cat avg_${str}.out | head -n 5 | tail -n 1`;
    val6=`cat avg_${str}.out | head -n 6 | tail -n 1`;
    val7=`cat avg_${str}.out | head -n 7 | tail -n 1`;
    val8=`cat avg_${str}.out | head -n 8 | tail -n 1`;
    val9=`cat avg_${str}.out | head -n 9 | tail -n 1`;
    val10=`cat avg_${str}.out | head -n 10 | tail -n 1`;
    
    # 判断数据是否是正的
    val11=`echo "a=$val1 - $time;if(0>a)a*=-1;a" | bc 2>&1`;
    test_err=`echo "$val11" | grep error`;
    if ! [ -z "$test_err" ]; then
	echo "[ERROR] Program output does not match expected single-line with time."    ;
	# echo "[ERROR] The program must be a PolyBench, compiled with -DPOLYBENCH_TIME"  ;
	exit 1;
    fi;
    # 计算每份数据和平均值的差值的绝对值
    val12=`echo "a=$val2 - $time;if(0>a)a*=-1;a" | bc`;
    val13=`echo "a=$val3 - $time;if(0>a)a*=-1;a" | bc`;
    val14=`echo "a=$val4 - $time;if(0>a)a*=-1;a" | bc`;
    val15=`echo "a=$val5 - $time;if(0>a)a*=-1;a" | bc`;
    val16=`echo "a=$val6 - $time;if(0>a)a*=-1;a" | bc`;
    val17=`echo "a=$val7 - $time;if(0>a)a*=-1;a" | bc`;
    val18=`echo "a=$val8 - $time;if(0>a)a*=-1;a" | bc`;
    val19=`echo "a=$val9 - $time;if(0>a)a*=-1;a" | bc`;
    val20=`echo "a=$val10 - $time;if(0>a)a*=-1;a" | bc`;

    # 计算其中最大的偏差
    myvar=`echo "$val11 $val12 $val13" | awk '{ if ($1 > $2) { if ($1 > $3) print $1; else print $3; } else { if ($2 > $3) print $2; else print $3; } }'`;
    myvar=`echo "$myvar $val14 $val15" | awk '{ if ($1 > $2) { if ($1 > $3) print $1; else print $3; } else { if ($2 > $3) print $2; else print $3; } }'`;
    myvar=`echo "$myvar $val16 $val17" | awk '{ if ($1 > $2) { if ($1 > $3) print $1; else print $3; } else { if ($2 > $3) print $2; else print $3; } }'`;
    myvar=`echo "$myvar $val18 $val19" | awk '{ if ($1 > $2) { if ($1 > $3) print $1; else print $3; } else { if ($2 > $3) print $2; else print $3; } }'`;
    myvar=`echo "$myvar $val20" | awk '{ if ($1 > $2) { print $1; } else { print $2; } }'`;

    variance=`echo "scale=8;($myvar/$time)*100" | bc`;
    tmp=`echo "$variance" | cut -d '.' -f 1`;
    if [ -z "$tmp" ]; then
	variance="0$variance";
    fi;
    compvar=`echo "$variance $VARIANCE_ACCEPTED" | awk '{ if ($1 < $2) print "ok"; else print "error"; }'`;
    if [ "$compvar" = "error" ]; then
    # echo "[WARNING] Variance is above thresold, unsafe performance measurement, => max deviation=$variance%, tolerance=$VARIANCE_ACCEPTED%, in running $benchcomputed"  ;
	WARNING_VARIANCE="$WARNING_VARIANCE\n$benchcomputed: max deviation=$variance%, tolerance=$VARIANCE_ACCEPTED%";
    # else
	# echo "[INFO] Maximal deviation from arithmetic mean of 10 average runs: $variance%, in running $benchcomputed."  ;
    fi;
    # PROCESSED_TIME="$time";
    VARIANCE_TEST="$variance";
    rm -f avg_${str}.out;
    
    # echo "[INFO] Normalized time: $PROCESSED_TIME, 4D Check time: $CHECK_TIME" ;
}

# 进行编译运行的Profiling过程
if [[ ${ERROR_READY} = true ]]; then
    # 设置必要的参数
    time_array=()
    # init variance of test is 100 
    VARIANCE_TEST=100;
    if [ $DEBUG_TYPE -eq 1 ]; then
        echo "lnlamp: message: The Profiling Rate is: ${rate_array[0]} ${rate_array[1]} ${rate_array[2]} ${rate_array[3]} ${rate_array[4]} ${rate_array[5]} ${rate_array[6]} ${rate_array[7]} ${rate_array[8]}."
        echo "lnlamp: message: The   PPCG   FLAGS is: ${PPCG_ISL_FLAGS} ${PPCG_SCHEDULE_FLAGS} ${PPCG_TILE_FLAGS} ${PPCG_OPENMP_FLAGS}."
        echo "lnlamp: message: The  Compiler  CMD is: ${VERBOSE} ${CC} ${CFLAGS} ${LIB_FLAGS} ${PROFILER_FLAGS} ${EXIT_FLAGS}."
    fi

    # 并行地进行PPCG_Codegen并编译
    {
        ppcg --target c --no-automatic-mixed-precision ${PPCG_ISL_FLAGS} ${PPCG_SCHEDULE_FLAGS} ${PPCG_TILE_FLAGS} ${PPCG_OPENMP_FLAGS} $src_args -o ____lnlamp_ppcg__${prf_suf} > /dev/null 2>&1
        if [ $? -ne 0 ]; then
            echo "lnlamp: error: PPCG Codegen meets errors."
            echo "lnlamp: error: The PPCG CMD is : ppcg --target c --no-automatic-mixed-precision ${PPCG_ISL_FLAGS} ${PPCG_SCHEDULE_FLAGS} ${PPCG_TILE_FLAGS} ${PPCG_OPENMP_FLAGS} $src_args -o ____lnlamp_ppcg__${prf_suf} "
            exit
        fi
        ${VERBOSE} ${CC} ${CFLAGS} ${LIB_FLAGS} ${PROFILER_FLAGS} ____lnlamp_ppcg__${prf_suf} -o  ____lnlamp_ppcg__.exe ${EXIT_FLAGS} > /dev/null 2>&1
        if [ $? -ne 0 ]; then
            echo "lnlamp: error: Compiling meets errors."
            echo "lnlamp: error: The compiler CMD is : ${VERBOSE} ${CC} ${CFLAGS} ${LIB_FLAGS} ${PROFILER_FLAGS} ____lnlamp_ppcg__${prf_suf} -o  ____lnlamp_ppcg__.exe ${EXIT_FLAGS}"
            exit
        fi
        rm -f ____lnlamp_ppcg__${prf_suf}
    }&
    {
        ppcg --target c -R ${rate_array[0]} ${PPCG_ISL_FLAGS} ${PPCG_SCHEDULE_FLAGS} ${PPCG_TILE_FLAGS} ${PPCG_OPENMP_FLAGS} $src_args -o ____lnlamp_${rate_array[0]}__${prf_suf} > /dev/null 2>&1
        if [ $? -ne 0 ]; then
            echo "lnlamp: error: PPCG Codegen meets errors."
            echo "lnlamp: error: The PPCG CMD is : ppcg --target c -R ${rate_array[0]} ${PPCG_ISL_FLAGS} ${PPCG_SCHEDULE_FLAGS} ${PPCG_TILE_FLAGS} ${PPCG_OPENMP_FLAGS} $src_args -o ____lnlamp_${rate_array[0]}__${prf_suf} "
            exit
        fi
        ${VERBOSE} ${CC} ${CFLAGS} ${LIB_FLAGS} ${PROFILER_FLAGS} ____lnlamp_${rate_array[0]}__${prf_suf} -o  ____lnlamp_${rate_array[0]}__.exe  ${EXIT_FLAGS}  > /dev/null 2>&1
        if [ $? -ne 0 ]; then
            echo "lnlamp: error: Compiling meets errors."
            echo "lnlamp: error: The compiler CMD is : ${VERBOSE} ${CC} ${CFLAGS} ${LIB_FLAGS} ${PROFILER_FLAGS} ____lnlamp_${rate_array[0]}__${prf_suf} -o  ____lnlamp_${rate_array[0]}__.exe  ${EXIT_FLAGS}"
            exit
        fi
        rm -f ____lnlamp_${rate_array[0]}__${prf_suf}
    }&
    wait
    {
        ppcg --target c -R ${rate_array[1]} ${PPCG_ISL_FLAGS} ${PPCG_SCHEDULE_FLAGS} ${PPCG_TILE_FLAGS} ${PPCG_OPENMP_FLAGS} $src_args -o ____lnlamp_${rate_array[1]}__${prf_suf} > /dev/null 2>&1
        if [ $? -ne 0 ]; then
            echo "lnlamp: error: PPCG Codegen meets errors."
            echo "lnlamp: error: The PPCG CMD is : ppcg --target c -R ${rate_array[1]} ${PPCG_ISL_FLAGS} ${PPCG_SCHEDULE_FLAGS} ${PPCG_TILE_FLAGS} ${PPCG_OPENMP_FLAGS} $src_args -o ____lnlamp_${rate_array[1]}__${prf_suf} "
            exit
        fi
        ${VERBOSE} ${CC} ${CFLAGS} ${LIB_FLAGS} ${PROFILER_FLAGS} ____lnlamp_${rate_array[1]}__${prf_suf} -o  ____lnlamp_${rate_array[1]}__.exe  ${EXIT_FLAGS}  > /dev/null 2>&1
        if [ $? -ne 0 ]; then
            echo "lnlamp: error: Compiling meets errors."
            echo "lnlamp: error: The compiler CMD is : ${VERBOSE} ${CC} ${CFLAGS} ${LIB_FLAGS} ${PROFILER_FLAGS} ____lnlamp_${rate_array[1]}__${prf_suf} -o  ____lnlamp_${rate_array[1]}__.exe  ${EXIT_FLAGS}"
            exit
        fi
        rm -f ____lnlamp_${rate_array[1]}__${prf_suf}
    }&
    {
        ppcg --target c -R ${rate_array[2]} ${PPCG_ISL_FLAGS} ${PPCG_SCHEDULE_FLAGS} ${PPCG_TILE_FLAGS} ${PPCG_OPENMP_FLAGS} $src_args -o ____lnlamp_${rate_array[2]}__${prf_suf} > /dev/null 2>&1
        if [ $? -ne 0 ]; then
            echo "lnlamp: error: PPCG Codegen meets errors."
            echo "lnlamp: error: The PPCG CMD is : ppcg --target c -R ${rate_array[2]} ${PPCG_ISL_FLAGS} ${PPCG_SCHEDULE_FLAGS} ${PPCG_TILE_FLAGS} ${PPCG_OPENMP_FLAGS} $src_args -o ____lnlamp_${rate_array[2]}__${prf_suf} "
            exit
        fi
        ${VERBOSE} ${CC} ${CFLAGS} ${LIB_FLAGS} ${PROFILER_FLAGS} ____lnlamp_${rate_array[2]}__${prf_suf} -o  ____lnlamp_${rate_array[2]}__.exe  ${EXIT_FLAGS} > /dev/null 2>&1
        if [ $? -ne 0 ]; then
            echo "lnlamp: error: Compiling meets errors."
            echo "lnlamp: error: The compiler CMD is : ${VERBOSE} ${CC} ${CFLAGS} ${LIB_FLAGS} ${PROFILER_FLAGS} ____lnlamp_${rate_array[2]}__${prf_suf} -o  ____lnlamp_${rate_array[2]}__.exe  ${EXIT_FLAGS} "
            exit
        fi
        rm -f ____lnlamp_${rate_array[2]}__${prf_suf}
    }&
    wait
    {
        ppcg --target c -R ${rate_array[3]} ${PPCG_ISL_FLAGS} ${PPCG_SCHEDULE_FLAGS} ${PPCG_TILE_FLAGS} ${PPCG_OPENMP_FLAGS} $src_args -o ____lnlamp_${rate_array[3]}__${prf_suf} > /dev/null 2>&1
        if [ $? -ne 0 ]; then
            echo "lnlamp: error: PPCG Codegen meets errors."
            echo "lnlamp: error: The PPCG CMD is : ppcg --target c -R ${rate_array[3]} ${PPCG_ISL_FLAGS} ${PPCG_SCHEDULE_FLAGS} ${PPCG_TILE_FLAGS} ${PPCG_OPENMP_FLAGS} $src_args -o ____lnlamp_${rate_array[3]}__${prf_suf} "
            exit
        fi
        ${VERBOSE} ${CC} ${CFLAGS} ${LIB_FLAGS} ${PROFILER_FLAGS} ____lnlamp_${rate_array[3]}__${prf_suf} -o  ____lnlamp_${rate_array[3]}__.exe  ${EXIT_FLAGS} > /dev/null 2>&1
        if [ $? -ne 0 ]; then
            echo "lnlamp: error: Compiling meets errors."
            echo "lnlamp: error: The compiler CMD is : ${VERBOSE} ${CC} ${CFLAGS} ${LIB_FLAGS} ${PROFILER_FLAGS} ____lnlamp_${rate_array[3]}__${prf_suf} -o  ____lnlamp_${rate_array[3]}__.exe  ${EXIT_FLAGS} "
            exit
        fi
        rm -f ____lnlamp_${rate_array[3]}__${prf_suf}
    }&
    {
        ppcg --target c -R ${rate_array[4]} ${PPCG_ISL_FLAGS} ${PPCG_SCHEDULE_FLAGS} ${PPCG_TILE_FLAGS} ${PPCG_OPENMP_FLAGS} $src_args -o ____lnlamp_${rate_array[4]}__${prf_suf} > /dev/null 2>&1
        if [ $? -ne 0 ]; then
            echo "lnlamp: error: PPCG Codegen meets errors."
            echo "lnlamp: error: The PPCG CMD is : ppcg --target c -R ${rate_array[4]} ${PPCG_ISL_FLAGS} ${PPCG_SCHEDULE_FLAGS} ${PPCG_TILE_FLAGS} ${PPCG_OPENMP_FLAGS} $src_args -o ____lnlamp_${rate_array[4]}__${prf_suf} "
            exit
        fi
        ${VERBOSE} ${CC} ${CFLAGS} ${LIB_FLAGS} ${PROFILER_FLAGS} ____lnlamp_${rate_array[4]}__${prf_suf} -o  ____lnlamp_${rate_array[4]}__.exe  ${EXIT_FLAGS} > /dev/null 2>&1
        if [ $? -ne 0 ]; then
            echo "lnlamp: error: Compiling meets errors."
            echo "lnlamp: error: The compiler CMD is : ${VERBOSE} ${CC} ${CFLAGS} ${LIB_FLAGS} ${PROFILER_FLAGS} ____lnlamp_${rate_array[4]}__${prf_suf} -o  ____lnlamp_${rate_array[4]}__.exe  ${EXIT_FLAGS} "
            exit
        fi
        rm -f ____lnlamp_${rate_array[4]}__${prf_suf}
    }&
    wait
    {
        ppcg --target c -R ${rate_array[5]} ${PPCG_ISL_FLAGS} ${PPCG_SCHEDULE_FLAGS} ${PPCG_TILE_FLAGS} ${PPCG_OPENMP_FLAGS} $src_args -o ____lnlamp_${rate_array[5]}__${prf_suf} > /dev/null 2>&1
        if [ $? -ne 0 ]; then
            echo "lnlamp: error: PPCG Codegen meets errors."
            echo "lnlamp: error: The PPCG CMD is : ppcg --target c -R ${rate_array[5]} ${PPCG_ISL_FLAGS} ${PPCG_SCHEDULE_FLAGS} ${PPCG_TILE_FLAGS} ${PPCG_OPENMP_FLAGS} $src_args -o ____lnlamp_${rate_array[5]}__${prf_suf} "
            exit
        fi
        ${VERBOSE} ${CC} ${CFLAGS} ${LIB_FLAGS} ${PROFILER_FLAGS} ____lnlamp_${rate_array[5]}__${prf_suf} -o  ____lnlamp_${rate_array[5]}__.exe  ${EXIT_FLAGS} > /dev/null 2>&1
        if [ $? -ne 0 ]; then
            echo "lnlamp: error: Compiling meets errors."
            echo "lnlamp: error: The compiler CMD is : ${VERBOSE} ${CC} ${CFLAGS} ${LIB_FLAGS} ${PROFILER_FLAGS} ____lnlamp_${rate_array[5]}__${prf_suf} -o  ____lnlamp_${rate_array[5]}__.exe  ${EXIT_FLAGS} "
            exit
        fi
        rm -f ____lnlamp_${rate_array[5]}__${prf_suf}
    }&
    {
        ppcg --target c -R ${rate_array[6]} ${PPCG_ISL_FLAGS} ${PPCG_SCHEDULE_FLAGS} ${PPCG_TILE_FLAGS} ${PPCG_OPENMP_FLAGS} $src_args -o ____lnlamp_${rate_array[6]}__${prf_suf} > /dev/null 2>&1
        if [ $? -ne 0 ]; then
            echo "lnlamp: error: PPCG Codegen meets errors."
            echo "lnlamp: error: The PPCG CMD is : ppcg --target c -R ${rate_array[6]} ${PPCG_ISL_FLAGS} ${PPCG_SCHEDULE_FLAGS} ${PPCG_TILE_FLAGS} ${PPCG_OPENMP_FLAGS} $src_args -o ____lnlamp_${rate_array[6]}__${prf_suf} "
            exit
        fi
        ${VERBOSE} ${CC} ${CFLAGS} ${LIB_FLAGS} ${PROFILER_FLAGS} ____lnlamp_${rate_array[6]}__${prf_suf} -o  ____lnlamp_${rate_array[6]}__.exe  ${EXIT_FLAGS} > /dev/null 2>&1
        if [ $? -ne 0 ]; then
            echo "lnlamp: error: Compiling meets errors."
            echo "lnlamp: error: The compiler CMD is : ${VERBOSE} ${CC} ${CFLAGS} ${LIB_FLAGS} ${PROFILER_FLAGS} ____lnlamp_${rate_array[6]}__${prf_suf} -o  ____lnlamp_${rate_array[6]}__.exe  ${EXIT_FLAGS} "
            exit
        fi
        rm -f ____lnlamp_${rate_array[6]}__${prf_suf}
    }&
    wait
    {
        ppcg --target c -R ${rate_array[7]} ${PPCG_ISL_FLAGS} ${PPCG_SCHEDULE_FLAGS} ${PPCG_TILE_FLAGS} ${PPCG_OPENMP_FLAGS} $src_args -o ____lnlamp_${rate_array[7]}__${prf_suf} > /dev/null 2>&1
        if [ $? -ne 0 ]; then
            echo "lnlamp: error: PPCG Codegen meets errors."
            echo "lnlamp: error: The PPCG CMD is : ppcg --target c -R ${rate_array[7]} ${PPCG_ISL_FLAGS} ${PPCG_SCHEDULE_FLAGS} ${PPCG_TILE_FLAGS} ${PPCG_OPENMP_FLAGS} $src_args -o ____lnlamp_${rate_array[7]}__${prf_suf} "
            exit
        fi
        ${VERBOSE} ${CC} ${CFLAGS} ${LIB_FLAGS} ${PROFILER_FLAGS} ____lnlamp_${rate_array[7]}__${prf_suf} -o  ____lnlamp_${rate_array[7]}__.exe  ${EXIT_FLAGS} > /dev/null 2>&1
        if [ $? -ne 0 ]; then
            echo "lnlamp: error: Compiling meets errors."
            echo "lnlamp: error: The compiler CMD is : ${VERBOSE} ${CC} ${CFLAGS} ${LIB_FLAGS} ${PROFILER_FLAGS} ____lnlamp_${rate_array[7]}__${prf_suf} -o  ____lnlamp_${rate_array[7]}__.exe  ${EXIT_FLAGS} "
            exit
        fi
        rm -f ____lnlamp_${rate_array[7]}__${prf_suf}
    }&
    {
        ppcg --target c -R ${rate_array[8]} ${PPCG_ISL_FLAGS} ${PPCG_SCHEDULE_FLAGS} ${PPCG_TILE_FLAGS} ${PPCG_OPENMP_FLAGS} $src_args -o ____lnlamp_${rate_array[8]}__${prf_suf} > /dev/null 2>&1
        if [ $? -ne 0 ]; then
            echo "lnlamp: error: PPCG Codegen meets errors."
            echo "lnlamp: error: The PPCG CMD is : ppcg --target c -R ${rate_array[8]} ${PPCG_ISL_FLAGS} ${PPCG_SCHEDULE_FLAGS} ${PPCG_TILE_FLAGS} ${PPCG_OPENMP_FLAGS} $src_args -o ____lnlamp_${rate_array[8]}__${prf_suf} "
            exit
        fi
        ${VERBOSE} ${CC} ${CFLAGS} ${LIB_FLAGS} ${PROFILER_FLAGS} ____lnlamp_${rate_array[8]}__${prf_suf} -o  ____lnlamp_${rate_array[8]}__.exe  ${EXIT_FLAGS} > /dev/null 2>&1
        if [ $? -ne 0 ]; then
            echo "lnlamp: error: Compiling meets errors."
            echo "lnlamp: error: The compiler CMD is : ${VERBOSE} ${CC} ${CFLAGS} ${LIB_FLAGS} ${PROFILER_FLAGS} ____lnlamp_${rate_array[8]}__${prf_suf} -o  ____lnlamp_${rate_array[8]}__.exe  ${EXIT_FLAGS} "
            exit
        fi
        rm -f ____lnlamp_${rate_array[8]}__${prf_suf}
    }&
    wait

    # 设置Timing
    if [ $timing_type -eq 1 ];
    then 
        timing="time -f %e"
        if [ $DEBUG_TYPE -eq 1 ];then
            echo "lnlamp: message: The Timing CMD is: '${timing}'."
        fi
    else
        timing=""
        if [ $DEBUG_TYPE -eq 1 ];then
            echo "lnlamp: message: The Timing result is in the program, which means the only output of the program is timing result."
        fi
    fi

    # Profiling (default input file is input.txt)
    # 设置线程的数量
    export OMP_NUM_THREADS=$num_threads;
    if [ "$PPCG_OPENMP_FLAGS" = "--openmp" -a $DEBUG_TYPE -eq 1 ];
    then
        echo "lnlamp: message: Profiling will using $OMP_NUM_THREADS threads to run."
    fi
    if [ -e $input ];
    then
        if [ $DEBUG_TYPE -eq 1 ];then
            echo "lnlamp: message: Profiling will use the $input file ."
        fi
        {
            # initial variance is 100 
            VARIANCE_TEST=100;
            while [ `echo "$VARIANCE_TEST > $VARIANCE_ACCEPTED" | bc` -eq 1 ] 
            do
                { ${timing} ./____lnlamp_ppcg__.exe < $input > ____lnlamp_output_upper 2> /dev/null ; } 2> ____lnlamp_timing_upper
                { ${timing} ./____lnlamp_ppcg__.exe < $input > ____lnlamp_output_upper 2> /dev/null ; } 2> ____lnlamp_timing_upper
                for ((i=1; i<$frequency; i++))
                do
                    { ${timing} ./____lnlamp_ppcg__.exe < $input >> ____lnlamp_output_upper 2> /dev/null ; } 2>> ____lnlamp_timing_upper
                done
                if [ $timing_type -eq 1 ];
                then
                    # 计算方差
                    compute_mean_exec_time ____lnlamp_timing_upper ____lnlamp_ppcg__.exe;
                else
                    # 计算方差
                    compute_mean_exec_time ____lnlamp_output_upper ____lnlamp_ppcg__.exe;
                fi
            done
            rm -f ____lnlamp_ppcg__.exe
        }&
        wait
        {
            # initial variance is 100 
            VARIANCE_TEST=100;
            while [ `echo "$VARIANCE_TEST > $VARIANCE_ACCEPTED" | bc` -eq 1 ] 
            do
                { ${timing} ./____lnlamp_${rate_array[0]}__.exe < $input > ____lnlamp_output_mix_0 2> /dev/null ; } 2> ____lnlamp_timing_mix_0
                { ${timing} ./____lnlamp_${rate_array[0]}__.exe < $input > ____lnlamp_output_mix_0 2> /dev/null ; } 2> ____lnlamp_timing_mix_0
                for ((i=1; i<$frequency; i++))
                do
                    { ${timing} ./____lnlamp_${rate_array[0]}__.exe < $input >> ____lnlamp_output_mix_0 2> /dev/null ; } 2>> ____lnlamp_timing_mix_0
                done
                if [ $timing_type -eq 1 ];
                then
                    # 计算方差
                    compute_mean_exec_time  ____lnlamp_timing_mix_0  ____lnlamp_${rate_array[0]}__.exe;
                else
                    # 计算方差
                    compute_mean_exec_time  ____lnlamp_output_mix_0  ____lnlamp_${rate_array[0]}__.exe;
                fi
            done
            rm -f ____lnlamp_${rate_array[0]}__.exe
        }&
        wait
        {
            # initial variance is 100 
            VARIANCE_TEST=100;
            while [ `echo "$VARIANCE_TEST > $VARIANCE_ACCEPTED" | bc` -eq 1 ] 
            do
                { ${timing} ./____lnlamp_${rate_array[1]}__.exe < $input > ____lnlamp_output_mix_1 2> /dev/null ; } 2> ____lnlamp_timing_mix_1
                { ${timing} ./____lnlamp_${rate_array[1]}__.exe < $input > ____lnlamp_output_mix_1 2> /dev/null ; } 2> ____lnlamp_timing_mix_1
                for ((i=1; i<$frequency; i++))
                do
                    { ${timing} ./____lnlamp_${rate_array[1]}__.exe < $input >> ____lnlamp_output_mix_1 2> /dev/null ; } 2>> ____lnlamp_timing_mix_1
                done
                if [ $timing_type -eq 1 ];
                then
                    # 计算方差
                    compute_mean_exec_time  ____lnlamp_timing_mix_1  ____lnlamp_${rate_array[1]}__.exe;
                else
                    # 计算方差
                    compute_mean_exec_time  ____lnlamp_output_mix_1  ____lnlamp_${rate_array[1]}__.exe;
                fi
            done
            rm -f ____lnlamp_${rate_array[1]}__.exe
        }&
        wait
        {
            # initial variance is 100 
            VARIANCE_TEST=100;
            while [ `echo "$VARIANCE_TEST > $VARIANCE_ACCEPTED" | bc` -eq 1 ] 
            do
                { ${timing} ./____lnlamp_${rate_array[2]}__.exe < $input > ____lnlamp_output_mix_2 2> /dev/null ; } 2> ____lnlamp_timing_mix_2
                { ${timing} ./____lnlamp_${rate_array[2]}__.exe < $input > ____lnlamp_output_mix_2 2> /dev/null ; } 2> ____lnlamp_timing_mix_2
                for ((i=1; i<$frequency; i++))
                do
                    { ${timing} ./____lnlamp_${rate_array[2]}__.exe < $input >> ____lnlamp_output_mix_2 2> /dev/null ; } 2>> ____lnlamp_timing_mix_2
                done
                if [ $timing_type -eq 1 ];
                then
                    # 计算方差
                    compute_mean_exec_time  ____lnlamp_timing_mix_2  ____lnlamp_${rate_array[2]}__.exe;
                else
                    # 计算方差
                    compute_mean_exec_time  ____lnlamp_output_mix_2  ____lnlamp_${rate_array[2]}__.exe;
                fi
            done
            rm -f ____lnlamp_${rate_array[2]}__.exe
        }&
        wait
        {
            # initial variance is 100 
            VARIANCE_TEST=100;
            while [ `echo "$VARIANCE_TEST > $VARIANCE_ACCEPTED" | bc` -eq 1 ] 
            do
                { ${timing} ./____lnlamp_${rate_array[3]}__.exe < $input > ____lnlamp_output_mix_3 2> /dev/null ; } 2> ____lnlamp_timing_mix_3
                { ${timing} ./____lnlamp_${rate_array[3]}__.exe < $input > ____lnlamp_output_mix_3 2> /dev/null ; } 2> ____lnlamp_timing_mix_3
                for ((i=1; i<$frequency; i++))
                do
                    { ${timing} ./____lnlamp_${rate_array[3]}__.exe < $input >> ____lnlamp_output_mix_3 2> /dev/null ; } 2>> ____lnlamp_timing_mix_3
                done
                if [ $timing_type -eq 1 ];
                then
                    # 计算方差
                    compute_mean_exec_time  ____lnlamp_timing_mix_3  ____lnlamp_${rate_array[3]}__.exe;
                else
                    # 计算方差
                    compute_mean_exec_time  ____lnlamp_output_mix_3  ____lnlamp_${rate_array[3]}__.exe;
                fi
            done
            rm -f ____lnlamp_${rate_array[3]}__.exe
        }&
        wait
        {
            # initial variance is 100 
            VARIANCE_TEST=100;
            while [ `echo "$VARIANCE_TEST > $VARIANCE_ACCEPTED" | bc` -eq 1 ] 
            do
                { ${timing} ./____lnlamp_${rate_array[4]}__.exe < $input > ____lnlamp_output_mix_4 2> /dev/null ; } 2> ____lnlamp_timing_mix_4
                { ${timing} ./____lnlamp_${rate_array[4]}__.exe < $input > ____lnlamp_output_mix_4 2> /dev/null ; } 2> ____lnlamp_timing_mix_4
                for ((i=1; i<$frequency; i++))
                do
                    { ${timing} ./____lnlamp_${rate_array[4]}__.exe < $input >> ____lnlamp_output_mix_4 2> /dev/null ; } 2>> ____lnlamp_timing_mix_4
                done
                if [ $timing_type -eq 1 ];
                then
                    # 计算方差
                    compute_mean_exec_time  ____lnlamp_timing_mix_4  ____lnlamp_${rate_array[4]}__.exe;
                else
                    # 计算方差
                    compute_mean_exec_time  ____lnlamp_output_mix_4  ____lnlamp_${rate_array[4]}__.exe;
                fi
            done
            rm -f ____lnlamp_${rate_array[4]}__.exe
        }&
        wait
        {
            # initial variance is 100 
            VARIANCE_TEST=100;
            while [ `echo "$VARIANCE_TEST > $VARIANCE_ACCEPTED" | bc` -eq 1 ] 
            do
                { ${timing} ./____lnlamp_${rate_array[5]}__.exe < $input > ____lnlamp_output_mix_5 2> /dev/null ; } 2> ____lnlamp_timing_mix_5
                { ${timing} ./____lnlamp_${rate_array[5]}__.exe < $input > ____lnlamp_output_mix_5 2> /dev/null ; } 2> ____lnlamp_timing_mix_5
                for ((i=1; i<$frequency; i++))
                do
                    { ${timing} ./____lnlamp_${rate_array[5]}__.exe < $input >> ____lnlamp_output_mix_5 2> /dev/null ; } 2>> ____lnlamp_timing_mix_5
                done
                if [ $timing_type -eq 1 ];
                then
                    # 计算方差
                    compute_mean_exec_time  ____lnlamp_timing_mix_5  ____lnlamp_${rate_array[5]}__.exe;
                else
                    # 计算方差
                    compute_mean_exec_time  ____lnlamp_output_mix_5  ____lnlamp_${rate_array[5]}__.exe;
                fi
            done
            rm -f ____lnlamp_${rate_array[5]}__.exe
        }&
        wait
        {
            # initial variance is 100 
            VARIANCE_TEST=100;
            while [ `echo "$VARIANCE_TEST > $VARIANCE_ACCEPTED" | bc` -eq 1 ] 
            do
                { ${timing} ./____lnlamp_${rate_array[6]}__.exe < $input > ____lnlamp_output_mix_6 2> /dev/null ; } 2> ____lnlamp_timing_mix_6
                { ${timing} ./____lnlamp_${rate_array[6]}__.exe < $input > ____lnlamp_output_mix_6 2> /dev/null ; } 2> ____lnlamp_timing_mix_6
                for ((i=1; i<$frequency; i++))
                do
                    { ${timing} ./____lnlamp_${rate_array[6]}__.exe < $input >> ____lnlamp_output_mix_6 2> /dev/null ; } 2>> ____lnlamp_timing_mix_6
                done
                if [ $timing_type -eq 1 ];
                then
                    # 计算方差
                    compute_mean_exec_time  ____lnlamp_timing_mix_6  ____lnlamp_${rate_array[6]}__.exe;
                else
                    # 计算方差
                    compute_mean_exec_time  ____lnlamp_output_mix_6  ____lnlamp_${rate_array[6]}__.exe;
                fi
            done
            rm -f ____lnlamp_${rate_array[6]}__.exe
        }&
        wait
        {
            # initial variance is 100 
            VARIANCE_TEST=100;
            while [ `echo "$VARIANCE_TEST > $VARIANCE_ACCEPTED" | bc` -eq 1 ] 
            do
                { ${timing} ./____lnlamp_${rate_array[7]}__.exe < $input > ____lnlamp_output_mix_7 2> /dev/null ; } 2> ____lnlamp_timing_mix_7
                { ${timing} ./____lnlamp_${rate_array[7]}__.exe < $input > ____lnlamp_output_mix_7 2> /dev/null ; } 2> ____lnlamp_timing_mix_7
                for ((i=1; i<$frequency; i++))
                do
                    { ${timing} ./____lnlamp_${rate_array[7]}__.exe < $input >> ____lnlamp_output_mix_7 2> /dev/null ; } 2>> ____lnlamp_timing_mix_7
                done
                if [ $timing_type -eq 1 ];
                then
                    # 计算方差
                    compute_mean_exec_time  ____lnlamp_timing_mix_7  ____lnlamp_${rate_array[7]}__.exe;
                else
                    # 计算方差
                    compute_mean_exec_time  ____lnlamp_output_mix_7  ____lnlamp_${rate_array[7]}__.exe;
                fi
            done
            rm -f ____lnlamp_${rate_array[7]}__.exe
        }&
        wait
        {
            # initial variance is 100 
            VARIANCE_TEST=100;
            while [ `echo "$VARIANCE_TEST > $VARIANCE_ACCEPTED" | bc` -eq 1 ] 
            do
                { ${timing} ./____lnlamp_${rate_array[8]}__.exe < $input > ____lnlamp_output_mix_8 2> /dev/null ; } 2> ____lnlamp_timing_mix_8
                { ${timing} ./____lnlamp_${rate_array[8]}__.exe < $input > ____lnlamp_output_mix_8 2> /dev/null ; } 2> ____lnlamp_timing_mix_8
                for ((i=1; i<$frequency; i++))
                do
                    { ${timing} ./____lnlamp_${rate_array[8]}__.exe < $input >> ____lnlamp_output_mix_8 2> /dev/null ; } 2>> ____lnlamp_timing_mix_8
                done
                if [ $timing_type -eq 1 ];
                then
                    # 计算方差
                    compute_mean_exec_time  ____lnlamp_timing_mix_8  ____lnlamp_${rate_array[8]}__.exe;
                else
                    # 计算方差
                    compute_mean_exec_time  ____lnlamp_output_mix_8  ____lnlamp_${rate_array[8]}__.exe;
                fi
            done
            rm -f ____lnlamp_${rate_array[8]}__.exe
        }&
        wait
    else
        if [ $DEBUG_TYPE -eq 1 ];then
            echo "lnlamp: message: Profiling will not use any input file(which means the program does not require any input)."
        fi
        {
            # initial variance is 100 
            VARIANCE_TEST=100;
            while [ `echo "$VARIANCE_TEST > $VARIANCE_ACCEPTED" | bc` -eq 1 ] 
            do
                { ${timing} ./____lnlamp_ppcg__.exe > ____lnlamp_output_upper 2> /dev/null ; } 2> ____lnlamp_timing_upper
                { ${timing} ./____lnlamp_ppcg__.exe > ____lnlamp_output_upper 2> /dev/null ; } 2> ____lnlamp_timing_upper
                for ((i=1; i<$frequency; i++))
                do
                    { ${timing} ./____lnlamp_ppcg__.exe >> ____lnlamp_output_upper 2> /dev/null ; } 2>> ____lnlamp_timing_upper
                done
                if [ $timing_type -eq 1 ];
                then
                    # 计算方差
                    compute_mean_exec_time ____lnlamp_timing_upper ____lnlamp_ppcg__.exe;
                else
                    # 计算方差
                    compute_mean_exec_time ____lnlamp_output_upper ____lnlamp_ppcg__.exe;
                fi
            done
            rm -f ____lnlamp_ppcg__.exe
        }&
        wait
        {
            # initial variance is 100 
            VARIANCE_TEST=100;
            while [ `echo "$VARIANCE_TEST > $VARIANCE_ACCEPTED" | bc` -eq 1 ] 
            do
                { ${timing} ./____lnlamp_${rate_array[0]}__.exe > ____lnlamp_output_mix_0 2> /dev/null ; } 2> ____lnlamp_timing_mix_0
                { ${timing} ./____lnlamp_${rate_array[0]}__.exe > ____lnlamp_output_mix_0 2> /dev/null ; } 2> ____lnlamp_timing_mix_0
                for ((i=1; i<$frequency; i++))
                do
                    { ${timing} ./____lnlamp_${rate_array[0]}__.exe >> ____lnlamp_output_mix_0 2> /dev/null ; } 2>> ____lnlamp_timing_mix_0
                done
                if [ $timing_type -eq 1 ];
                then
                    # 计算方差
                    compute_mean_exec_time  ____lnlamp_timing_mix_0  ____lnlamp_${rate_array[0]}__.exe;
                else
                    # 计算方差
                    compute_mean_exec_time  ____lnlamp_output_mix_0  ____lnlamp_${rate_array[0]}__.exe;
                fi
            done
            rm -f ____lnlamp_${rate_array[0]}__.exe
        }&
        wait
        {
            # initial variance is 100 
            VARIANCE_TEST=100;
            while [ `echo "$VARIANCE_TEST > $VARIANCE_ACCEPTED" | bc` -eq 1 ] 
            do
                { ${timing} ./____lnlamp_${rate_array[1]}__.exe > ____lnlamp_output_mix_1 2> /dev/null ; } 2> ____lnlamp_timing_mix_1
                { ${timing} ./____lnlamp_${rate_array[1]}__.exe > ____lnlamp_output_mix_1 2> /dev/null ; } 2> ____lnlamp_timing_mix_1
                for ((i=1; i<$frequency; i++))
                do
                    { ${timing} ./____lnlamp_${rate_array[1]}__.exe >> ____lnlamp_output_mix_1 2> /dev/null ; } 2>> ____lnlamp_timing_mix_1
                done
                if [ $timing_type -eq 1 ];
                then
                    # 计算方差
                    compute_mean_exec_time  ____lnlamp_timing_mix_1  ____lnlamp_${rate_array[1]}__.exe;
                else
                    # 计算方差
                    compute_mean_exec_time  ____lnlamp_output_mix_1  ____lnlamp_${rate_array[1]}__.exe;
                fi
            done
            rm -f ____lnlamp_${rate_array[1]}__.exe
        }&
        wait
        {
            # initial variance is 100 
            VARIANCE_TEST=100;
            while [ `echo "$VARIANCE_TEST > $VARIANCE_ACCEPTED" | bc` -eq 1 ] 
            do
                { ${timing} ./____lnlamp_${rate_array[2]}__.exe > ____lnlamp_output_mix_2 2> /dev/null ; } 2> ____lnlamp_timing_mix_2
                { ${timing} ./____lnlamp_${rate_array[2]}__.exe > ____lnlamp_output_mix_2 2> /dev/null ; } 2> ____lnlamp_timing_mix_2
                for ((i=1; i<$frequency; i++))
                do
                    { ${timing} ./____lnlamp_${rate_array[2]}__.exe >> ____lnlamp_output_mix_2 2> /dev/null ; } 2>> ____lnlamp_timing_mix_2
                done
                if [ $timing_type -eq 1 ];
                then
                    # 计算方差
                    compute_mean_exec_time  ____lnlamp_timing_mix_2  ____lnlamp_${rate_array[2]}__.exe;
                else
                    # 计算方差
                    compute_mean_exec_time  ____lnlamp_output_mix_2  ____lnlamp_${rate_array[2]}__.exe;
                fi
            done
            rm -f ____lnlamp_${rate_array[2]}__.exe
        }&
        wait
        {
            # initial variance is 100 
            VARIANCE_TEST=100;
            while [ `echo "$VARIANCE_TEST > $VARIANCE_ACCEPTED" | bc` -eq 1 ] 
            do
                { ${timing} ./____lnlamp_${rate_array[3]}__.exe > ____lnlamp_output_mix_3 2> /dev/null ; } 2> ____lnlamp_timing_mix_3
                { ${timing} ./____lnlamp_${rate_array[3]}__.exe > ____lnlamp_output_mix_3 2> /dev/null ; } 2> ____lnlamp_timing_mix_3
                for ((i=1; i<$frequency; i++))
                do
                    { ${timing} ./____lnlamp_${rate_array[3]}__.exe >> ____lnlamp_output_mix_3 2> /dev/null ; } 2>> ____lnlamp_timing_mix_3
                done
                if [ $timing_type -eq 1 ];
                then
                    # 计算方差
                    compute_mean_exec_time  ____lnlamp_timing_mix_3  ____lnlamp_${rate_array[3]}__.exe;
                else
                    # 计算方差
                    compute_mean_exec_time  ____lnlamp_output_mix_3  ____lnlamp_${rate_array[3]}__.exe;
                fi
            done
            rm -f ____lnlamp_${rate_array[3]}__.exe
        }&
        wait
        {
            # initial variance is 100 
            VARIANCE_TEST=100;
            while [ `echo "$VARIANCE_TEST > $VARIANCE_ACCEPTED" | bc` -eq 1 ] 
            do
                { ${timing} ./____lnlamp_${rate_array[4]}__.exe > ____lnlamp_output_mix_4 2> /dev/null ; } 2> ____lnlamp_timing_mix_4
                { ${timing} ./____lnlamp_${rate_array[4]}__.exe > ____lnlamp_output_mix_4 2> /dev/null ; } 2> ____lnlamp_timing_mix_4
                for ((i=1; i<$frequency; i++))
                do
                    { ${timing} ./____lnlamp_${rate_array[4]}__.exe >> ____lnlamp_output_mix_4 2> /dev/null ; } 2>> ____lnlamp_timing_mix_4
                done
                if [ $timing_type -eq 1 ];
                then
                    # 计算方差
                    compute_mean_exec_time  ____lnlamp_timing_mix_4  ____lnlamp_${rate_array[4]}__.exe;
                else
                    # 计算方差
                    compute_mean_exec_time  ____lnlamp_output_mix_4  ____lnlamp_${rate_array[4]}__.exe;
                fi
            done
            rm -f ____lnlamp_${rate_array[4]}__.exe
        }&
        wait
        {
            # initial variance is 100 
            VARIANCE_TEST=100;
            while [ `echo "$VARIANCE_TEST > $VARIANCE_ACCEPTED" | bc` -eq 1 ] 
            do
                { ${timing} ./____lnlamp_${rate_array[5]}__.exe > ____lnlamp_output_mix_5 2> /dev/null ; } 2> ____lnlamp_timing_mix_5
                { ${timing} ./____lnlamp_${rate_array[5]}__.exe > ____lnlamp_output_mix_5 2> /dev/null ; } 2> ____lnlamp_timing_mix_5
                for ((i=1; i<$frequency; i++))
                do
                    { ${timing} ./____lnlamp_${rate_array[5]}__.exe >> ____lnlamp_output_mix_5 2> /dev/null ; } 2>> ____lnlamp_timing_mix_5
                done
                if [ $timing_type -eq 1 ];
                then
                    # 计算方差
                    compute_mean_exec_time  ____lnlamp_timing_mix_5  ____lnlamp_${rate_array[5]}__.exe;
                else
                    # 计算方差
                    compute_mean_exec_time  ____lnlamp_output_mix_5  ____lnlamp_${rate_array[5]}__.exe;
                fi
            done
            rm -f ____lnlamp_${rate_array[5]}__.exe
        }&
        wait
        {
            # initial variance is 100 
            VARIANCE_TEST=100;
            while [ `echo "$VARIANCE_TEST > $VARIANCE_ACCEPTED" | bc` -eq 1 ] 
            do
                { ${timing} ./____lnlamp_${rate_array[6]}__.exe > ____lnlamp_output_mix_6 2> /dev/null ; } 2> ____lnlamp_timing_mix_6
                { ${timing} ./____lnlamp_${rate_array[6]}__.exe > ____lnlamp_output_mix_6 2> /dev/null ; } 2> ____lnlamp_timing_mix_6
                for ((i=1; i<$frequency; i++))
                do
                    { ${timing} ./____lnlamp_${rate_array[6]}__.exe >> ____lnlamp_output_mix_6 2> /dev/null ; } 2>> ____lnlamp_timing_mix_6
                done
                if [ $timing_type -eq 1 ];
                then
                    # 计算方差
                    compute_mean_exec_time  ____lnlamp_timing_mix_6  ____lnlamp_${rate_array[6]}__.exe;
                else
                    # 计算方差
                    compute_mean_exec_time  ____lnlamp_output_mix_6  ____lnlamp_${rate_array[6]}__.exe;
                fi
            done
            rm -f ____lnlamp_${rate_array[6]}__.exe
        }&
        wait
        {
            # initial variance is 100 
            VARIANCE_TEST=100;
            while [ `echo "$VARIANCE_TEST > $VARIANCE_ACCEPTED" | bc` -eq 1 ] 
            do
                { ${timing} ./____lnlamp_${rate_array[7]}__.exe > ____lnlamp_output_mix_7 2> /dev/null ; } 2> ____lnlamp_timing_mix_7
                { ${timing} ./____lnlamp_${rate_array[7]}__.exe > ____lnlamp_output_mix_7 2> /dev/null ; } 2> ____lnlamp_timing_mix_7
                for ((i=1; i<$frequency; i++))
                do
                    { ${timing} ./____lnlamp_${rate_array[7]}__.exe >> ____lnlamp_output_mix_7 2> /dev/null ; } 2>> ____lnlamp_timing_mix_7
                done
                if [ $timing_type -eq 1 ];
                then
                    # 计算方差
                    compute_mean_exec_time  ____lnlamp_timing_mix_7  ____lnlamp_${rate_array[7]}__.exe;
                else
                    # 计算方差
                    compute_mean_exec_time  ____lnlamp_output_mix_7  ____lnlamp_${rate_array[7]}__.exe;
                fi
            done
            rm -f ____lnlamp_${rate_array[7]}__.exe
        }&
        wait
        {
            # initial variance is 100 
            VARIANCE_TEST=100;
            while [ `echo "$VARIANCE_TEST > $VARIANCE_ACCEPTED" | bc` -eq 1 ] 
            do
                { ${timing} ./____lnlamp_${rate_array[8]}__.exe > ____lnlamp_output_mix_8 2> /dev/null ; } 2> ____lnlamp_timing_mix_8
                { ${timing} ./____lnlamp_${rate_array[8]}__.exe > ____lnlamp_output_mix_8 2> /dev/null ; } 2> ____lnlamp_timing_mix_8
                for ((i=1; i<$frequency; i++))
                do
                    { ${timing} ./____lnlamp_${rate_array[8]}__.exe >> ____lnlamp_output_mix_8 2> /dev/null ; } 2>> ____lnlamp_timing_mix_8
                done
                if [ $timing_type -eq 1 ];
                then
                    # 计算方差
                    compute_mean_exec_time  ____lnlamp_timing_mix_8  ____lnlamp_${rate_array[8]}__.exe;
                else
                    # 计算方差
                    compute_mean_exec_time  ____lnlamp_output_mix_8  ____lnlamp_${rate_array[8]}__.exe;
                fi
            done
            rm -f ____lnlamp_${rate_array[8]}__.exe
        }&
        wait
    fi

    # 编译4D检验法程序,如果编译可以通过,则用4d检验法求均值(可以自动去掉偏差),否则,直接求数值平均值.
    gcc -O3 $lnlamp_dir/4d_check.c -o 4d_check.exe > /dev/null 2>&1
    if [ $? -ne 0 ]; 
    then
        echo "lnlamp: WARNING: 4D_Check(4d_check.c) program meets errors, we will use the numerical averages without regard to deviations."
        # 根据Timing_type获取时间
        if [ $timing_type -eq 1 ];
        then
            # 说明程序的输出不是计时结果,删除____lnlamp_output_*
            rm -f ____lnlamp_output_*

            rows=$(awk 'END{print NR}' ____lnlamp_timing_upper);
            if [ $frequency -eq $rows ];
            then
                expr=0.0;
                while read n; 
                do
                    expr=$(echo $expr $n | awk '{ printf("%.10f",$1+$2); }');
                done < ____lnlamp_timing_upper;
                time_upper=$(echo $expr $frequency | awk '{ printf("%.10f",$1/$2); }');
            else
                echo "lnlamp: error: Parsing profile time meets errors."
                exit
            fi
            rm -f ____lnlamp_timing_upper

            rows=$(awk 'END{print NR}' ____lnlamp_timing_mix_0);
            if [ $frequency -eq $rows ];
            then 
                expr=0.0;
                while read n; 
                do
                    expr=$(echo $expr $n | awk '{ printf("%.10f",$1+$2); }');
                done < ____lnlamp_timing_mix_0;
                time_mix_0=$(echo $expr $frequency | awk '{ printf("%.10f",$1/$2); }');
            else
                echo "lnlamp: error: Parsing profile time meets errors."
                exit
            fi
            rm -f ____lnlamp_timing_mix_0

            rows=$(awk 'END{print NR}' ____lnlamp_timing_mix_1);
            if [ $frequency -eq $rows ];
            then 
                expr=0.0;
                while read n; 
                do
                    expr=$(echo $expr $n | awk '{ printf("%.10f",$1+$2); }');
                done < ____lnlamp_timing_mix_1;
                time_mix_1=$(echo $expr $frequency | awk '{ printf("%.10f",$1/$2); }');
            else
                echo "lnlamp: error: Parsing profile time meets errors."
                exit
            fi
            rm -f ____lnlamp_timing_mix_1

            rows=$(awk 'END{print NR}' ____lnlamp_timing_mix_2);
            if [ $frequency -eq $rows ];
            then 
                expr=0.0;
                while read n; 
                do
                    expr=$(echo $expr $n | awk '{ printf("%.10f",$1+$2); }');
                done < ____lnlamp_timing_mix_2;
                time_mix_2=$(echo $expr $frequency | awk '{ printf("%.10f",$1/$2); }');
            else
                echo "lnlamp: error: Parsing profile time meets errors."
                exit
            fi
            rm -f ____lnlamp_timing_mix_2

            rows=$(awk 'END{print NR}' ____lnlamp_timing_mix_3);
            if [ $frequency -eq $rows ];
            then
                expr=0.0;
                while read n;
                do
                    expr=$(echo $expr $n | awk '{ printf("%.10f",$1+$2); }');
                done < ____lnlamp_timing_mix_3;
                time_mix_3=$(echo $expr $frequency | awk '{ printf("%.10f",$1/$2); }');
            else
                echo "lnlamp: error: Parsing profile time meets errors."
                exit
            fi
            rm -f ____lnlamp_timing_mix_3

            rows=$(awk 'END{print NR}' ____lnlamp_timing_mix_4);
            if [ $frequency -eq $rows ];
            then
                expr=0.0;
                while read n;
                do
                    expr=$(echo $expr $n | awk '{ printf("%.10f",$1+$2); }');
                done < ____lnlamp_timing_mix_4;
                time_mix_4=$(echo $expr $frequency | awk '{ printf("%.10f",$1/$2); }');
            else
                echo "lnlamp: error: Parsing profile time meets errors."
                exit
            fi
            rm -f ____lnlamp_timing_mix_4

            rows=$(awk 'END{print NR}' ____lnlamp_timing_mix_5);
            if [ $frequency -eq $rows ];
            then
                expr=0.0;
                while read n;
                do
                    expr=$(echo $expr $n | awk '{ printf("%.10f",$1+$2); }');
                done < ____lnlamp_timing_mix_5;
                time_mix_5=$(echo $expr $frequency | awk '{ printf("%.10f",$1/$2); }');
            else
                echo "lnlamp: error: Parsing profile time meets errors."
                exit
            fi
            rm -f ____lnlamp_timing_mix_5

            rows=$(awk 'END{print NR}' ____lnlamp_timing_mix_6);
            if [ $frequency -eq $rows ];
            then
                expr=0.0;
                while read n;
                do
                    expr=$(echo $expr $n | awk '{ printf("%.10f",$1+$2); }');
                done < ____lnlamp_timing_mix_6;
                time_mix_6=$(echo $expr $frequency | awk '{ printf("%.10f",$1/$2); }');
            else
                echo "lnlamp: error: Parsing profile time meets errors."
                exit
            fi
            rm -f ____lnlamp_timing_mix_6

            rows=$(awk 'END{print NR}' ____lnlamp_timing_mix_7);
            if [ $frequency -eq $rows ];
            then
                expr=0.0;
                while read n;
                do
                    expr=$(echo $expr $n | awk '{ printf("%.10f",$1+$2); }');
                done < ____lnlamp_timing_mix_7;
                time_mix_7=$(echo $expr $frequency | awk '{ printf("%.10f",$1/$2); }');
            else
                echo "lnlamp: error: Parsing profile time meets errors."
                exit
            fi
            rm -f ____lnlamp_timing_mix_7

            rows=$(awk 'END{print NR}' ____lnlamp_timing_mix_8);
            if [ $frequency -eq $rows ];
            then
                expr=0.0;
                while read n;
                do
                    expr=$(echo $expr $n | awk '{ printf("%.10f",$1+$2); }');
                done < ____lnlamp_timing_mix_8;
                time_mix_8=$(echo $expr $frequency | awk '{ printf("%.10f",$1/$2); }');
            else
                echo "lnlamp: error: Parsing profile time meets errors."
                exit
            fi
            rm -f ____lnlamp_timing_mix_8
        else
            # 说明程序的输出是计时结果,则删除____lnlamp_timing_*
            rm -f ____lnlamp_timing_*

            rows=$(awk 'END{print NR}' ____lnlamp_output_upper);
            if [ $frequency -eq $rows ];
            then 
                expr=0.0;
                while read n; 
                do
                    expr=$(echo $expr $n | awk '{ printf("%.10f",$1+$2); }');
                done < ____lnlamp_output_upper;
                time_upper=$(echo $expr $frequency | awk '{ printf("%.10f",$1/$2); }');
            else
                echo "lnlamp: error: Parsing profile time meets errors."
                exit
            fi
            rm -f ____lnlamp_output_upper

            rows=$(awk 'END{print NR}' ____lnlamp_output_mix_0);
            if [ $frequency -eq $rows ];
            then 
                expr=0.0;
                while read n; 
                do
                    expr=$(echo $expr $n | awk '{ printf("%.10f",$1+$2); }');
                done < ____lnlamp_output_mix_0;
                time_mix_0=$(echo $expr $frequency | awk '{ printf("%.10f",$1/$2); }');
            else
                echo "lnlamp: error: Parsing profile time meets errors."
                exit
            fi
            rm -f ____lnlamp_output_mix_0

            rows=$(awk 'END{print NR}' ____lnlamp_output_mix_1);
            if [ $frequency -eq $rows ];
            then 
                expr=0.0;
                while read n; 
                do
                    expr=$(echo $expr $n | awk '{ printf("%.10f",$1+$2); }');
                done < ____lnlamp_output_mix_1;
                time_mix_1=$(echo $expr $frequency | awk '{ printf("%.10f",$1/$2); }');
            else
                echo "lnlamp: error: Parsing profile time meets errors."
                exit
            fi
            rm -f ____lnlamp_output_mix_1

            rows=$(awk 'END{print NR}' ____lnlamp_output_mix_2);
            if [ $frequency -eq $rows ];
            then 
                expr=0.0;
                while read n; 
                do
                    expr=$(echo $expr $n | awk '{ printf("%.10f",$1+$2); }');
                done < ____lnlamp_output_mix_2;
                time_mix_2=$(echo $expr $frequency | awk '{ printf("%.10f",$1/$2); }');
            else
                echo "lnlamp: error: Parsing profile time meets errors."
                exit
            fi
            rm -f ____lnlamp_output_mix_2

            rows=$(awk 'END{print NR}' ____lnlamp_output_mix_3);
            if [ $frequency -eq $rows ];
            then
                expr=0.0;
                while read n;
                do
                    expr=$(echo $expr $n | awk '{ printf("%.10f",$1+$2); }');
                done < ____lnlamp_output_mix_3;
                time_mix_3=$(echo $expr $frequency | awk '{ printf("%.10f",$1/$2); }');
            else
                echo "lnlamp: error: Parsing profile time meets errors."
                exit
            fi
            rm -f ____lnlamp_output_mix_3

            rows=$(awk 'END{print NR}' ____lnlamp_output_mix_4);
            if [ $frequency -eq $rows ];
            then
                expr=0.0;
                while read n;
                do
                    expr=$(echo $expr $n | awk '{ printf("%.10f",$1+$2); }');
                done < ____lnlamp_output_mix_4;
                time_mix_4=$(echo $expr $frequency | awk '{ printf("%.10f",$1/$2); }');
            else
                echo "lnlamp: error: Parsing profile time meets errors."
                exit
            fi
            rm -f ____lnlamp_output_mix_4

            rows=$(awk 'END{print NR}' ____lnlamp_output_mix_5);
            if [ $frequency -eq $rows ];
            then
                expr=0.0;
                while read n;
                do
                    expr=$(echo $expr $n | awk '{ printf("%.10f",$1+$2); }');
                done < ____lnlamp_output_mix_5;
                time_mix_5=$(echo $expr $frequency | awk '{ printf("%.10f",$1/$2); }');
            else
                echo "lnlamp: error: Parsing profile time meets errors."
                exit
            fi
            rm -f ____lnlamp_output_mix_5

            rows=$(awk 'END{print NR}' ____lnlamp_output_mix_6);
            if [ $frequency -eq $rows ];
            then
                expr=0.0;
                while read n;
                do
                    expr=$(echo $expr $n | awk '{ printf("%.10f",$1+$2); }');
                done < ____lnlamp_output_mix_6;
                time_mix_6=$(echo $expr $frequency | awk '{ printf("%.10f",$1/$2); }');
            else
                echo "lnlamp: error: Parsing profile time meets errors."
                exit
            fi
            rm -f ____lnlamp_output_mix_6

            rows=$(awk 'END{print NR}' ____lnlamp_output_mix_7);
            if [ $frequency -eq $rows ];
            then
                expr=0.0;
                while read n;
                do
                    expr=$(echo $expr $n | awk '{ printf("%.10f",$1+$2); }');
                done < ____lnlamp_output_mix_7;
                time_mix_7=$(echo $expr $frequency | awk '{ printf("%.10f",$1/$2); }');
            else
                echo "lnlamp: error: Parsing profile time meets errors."
                exit
            fi
            rm -f ____lnlamp_output_mix_7

            rows=$(awk 'END{print NR}' ____lnlamp_output_mix_8);
            if [ $frequency -eq $rows ];
            then
                expr=0.0;
                while read n;
                do
                    expr=$(echo $expr $n | awk '{ printf("%.10f",$1+$2); }');
                done < ____lnlamp_output_mix_8;
                time_mix_8=$(echo $expr $frequency | awk '{ printf("%.10f",$1/$2); }');
            else
                echo "lnlamp: error: Parsing profile time meets errors."
                exit
            fi
            rm -f ____lnlamp_output_mix_8
        fi
    # 4D检查程序可以使用.
    else
        # 根据Timing_type获取时间
        if [ $timing_type -eq 1 ];
        then
            # 说明程序的输出不是计时结果,删除____lnlamp_output_*
            rm -f ____lnlamp_output_*
            time_upper=`./4d_check.exe ____lnlamp_timing_upper`
            time_mix_0=`./4d_check.exe ____lnlamp_timing_mix_0`
            time_mix_1=`./4d_check.exe ____lnlamp_timing_mix_1`
            time_mix_2=`./4d_check.exe ____lnlamp_timing_mix_2`
            time_mix_3=`./4d_check.exe ____lnlamp_timing_mix_3`
            time_mix_4=`./4d_check.exe ____lnlamp_timing_mix_4`
            time_mix_5=`./4d_check.exe ____lnlamp_timing_mix_5`
            time_mix_6=`./4d_check.exe ____lnlamp_timing_mix_6`
            time_mix_7=`./4d_check.exe ____lnlamp_timing_mix_7`
            time_mix_8=`./4d_check.exe ____lnlamp_timing_mix_8`
            # 用完删掉
            rm -f ____lnlamp_timing_*
        else
            # 说明程序的输出是计时结果,则删除____lnlamp_timing_*
            rm -f ____lnlamp_timing_*
            time_upper=`./4d_check.exe ____lnlamp_output_upper`
            time_mix_0=`./4d_check.exe ____lnlamp_output_mix_0`
            time_mix_1=`./4d_check.exe ____lnlamp_output_mix_1`
            time_mix_2=`./4d_check.exe ____lnlamp_output_mix_2`
            time_mix_3=`./4d_check.exe ____lnlamp_output_mix_3`
            time_mix_4=`./4d_check.exe ____lnlamp_output_mix_4`
            time_mix_5=`./4d_check.exe ____lnlamp_output_mix_5`
            time_mix_6=`./4d_check.exe ____lnlamp_output_mix_6`
            time_mix_7=`./4d_check.exe ____lnlamp_output_mix_7`
            time_mix_8=`./4d_check.exe ____lnlamp_output_mix_8`
            # 用完删掉
            rm -f ____lnlamp_output_*
        fi
        rm -f 4d_check.exe
    fi
    if [ $DEBUG_TYPE -eq 1 ];then
        echo "lnlamp: message: Profiling times is(s): $time_upper $time_mix_0 $time_mix_1 $time_mix_2 $time_mix_3 $time_mix_4 $time_mix_5 $time_mix_6 $time_mix_7 $time_mix_8. "
    fi
    time_array+=( $(echo $time_upper $time_mix_0 | awk '{ printf("%.10f", $1-$2 ); }') );
    time_array+=( $(echo $time_upper $time_mix_1 | awk '{ printf("%.10f", $1-$2 ); }') );
    time_array+=( $(echo $time_upper $time_mix_2 | awk '{ printf("%.10f", $1-$2 ); }') );
    time_array+=( $(echo $time_upper $time_mix_3 | awk '{ printf("%.10f", $1-$2 ); }') );
    time_array+=( $(echo $time_upper $time_mix_4 | awk '{ printf("%.10f", $1-$2 ); }') );
    time_array+=( $(echo $time_upper $time_mix_5 | awk '{ printf("%.10f", $1-$2 ); }') );
    time_array+=( $(echo $time_upper $time_mix_6 | awk '{ printf("%.10f", $1-$2 ); }') );
    time_array+=( $(echo $time_upper $time_mix_7 | awk '{ printf("%.10f", $1-$2 ); }') );
    time_array+=( $(echo $time_upper $time_mix_8 | awk '{ printf("%.10f", $1-$2 ); }') );

    python3 $lnlamp_dir/lnlamp_internal_curve_fitting.py ${rate_array[0]} ${time_array[0]} ${rate_array[1]} ${time_array[1]} ${rate_array[2]} ${time_array[2]} ${rate_array[3]} ${time_array[3]} ${rate_array[4]} ${time_array[4]} ${rate_array[5]} ${time_array[5]} ${rate_array[6]} ${time_array[6]} ${rate_array[7]} ${time_array[7]} ${rate_array[8]} ${time_array[8]} >> lnlamp_internal_usage.py.log 2>&1
    if [ $? -ne 0 ]; then
        echo "lnlamp: error: Quadratic curve fitting(lnlamp_internal_curve_fitting.py) problems encountered!"
        echo "lnlamp: Quadratic curve fitting parameter is: ${rate_array[0]} ${time_array[0]} ${rate_array[1]} ${time_array[1]} ${rate_array[2]} ${time_array[2]} ${rate_array[3]} ${time_array[3]} ${rate_array[4]} ${time_array[4]} ${rate_array[5]} ${time_array[5]} ${rate_array[6]} ${time_array[6]} ${rate_array[7]} ${time_array[7]} ${rate_array[8]} ${time_array[8]} "
        exit
    fi
    #如果文件不存在，创建文件夹
    if [ ! -e "lnlamp_temp_result.txt" ]; then
        echo "lnlamp: error: Quadratic curve fitting(lnlamp_internal_curve_fitting.py) can't calculate the result!!!"
    else
        rows=$(awk 'END{print NR}' lnlamp_temp_result.txt);
        if [ 4 -eq $rows ];
        then
            poly_coeff=()
            while read n;
            do
                poly_coeff+=( $n )
            done < lnlamp_temp_result.txt;
            extremeValue=$(echo ${poly_coeff[3]} | awk '{ printf("%.10f",$1); }');
            equ_a=$(echo ${poly_coeff[2]} | awk '{ printf("%.10f",$1); }');
            equ_b=$(echo ${poly_coeff[1]} | awk '{ printf("%.10f",$1); }');
            equ_c=$(echo ${poly_coeff[0]} | awk '{ printf("%.10f",$1); }');
        else
            echo "lnlamp: error: The result of the calculation in quadratic curve fitting(lnlamp_internal_curve_fitting.py) is wrong!!!"
        fi
    fi
    rm -f lnlamp_temp_result.txt  lnlamp_internal_usage.py.log
    
    if [ $DEBUG_TYPE -eq 1 ];then
        echo "lnlamp: message: Quadratic curve fitting parameter is: ${rate_array[0]} ${time_array[0]} ${rate_array[1]} ${time_array[1]} ${rate_array[2]} ${time_array[2]} ${rate_array[3]} ${time_array[3]} ${rate_array[4]} ${time_array[4]} ${rate_array[5]} ${time_array[5]} ${rate_array[6]} ${time_array[6]} ${rate_array[7]} ${time_array[7]} ${rate_array[8]} ${time_array[8]}. "
        echo "lnlamp: message: Quadratic curve fitting's result  is: pi(r) = $equ_a * r^2 + $equ_b * r + $equ_c, the extreme value point is located at r = $extremeValue. "
    fi
    PROFILING_READY=true
fi
end=`date +%s%N`
time_profiling=$((($end-$start)/1000000)) # 毫秒


# 推理并获取最终结果
if [[ ${PROFILING_READY} = true ]]; then
    # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 
    # Step3: 根据抛物线和Profiling结果,确定最合适的Rate值
    # 使用 date +%s%N 可以获得一个纳秒级的unix时间戳(当前时间), 进行计时
    start=`date +%s%N`
    # 3.1 先确定最合适的Rate的可能取值
    best_rate=()
    amp_type=-2
    # 如果开口向下且对称轴小于0、或者开头向上且对称轴大于99,那么就是收益模型单调下降.
    if ([ $(echo "$extremeValue < $start_rate" | bc) -eq 1 ] && [ $(echo "$equ_a < 0" | bc) -eq 1 ]) || ([ $(echo "$extremeValue > $end_rate" | bc) -eq 1 ] && [ $(echo "$equ_a > 0" | bc) -eq 1 ]);
    then
        best_rate+=( $start_rate )
        amp_type=1
    # 如果开口向下且对称轴大于99、或者开头向上且对称轴小于0,那么就是收益模型单调上升.
    elif ([ $(echo "$extremeValue > $end_rate" | bc) -eq 1 ] && [ $(echo "$equ_a < 0" | bc) -eq 1 ]) || ([ $(echo "$extremeValue < $start_rate" | bc) -eq 1 ] && [ $(echo "$equ_a > 0" | bc) -eq 1 ]);
    then
        best_rate+=( $end_rate )
        amp_type=2
    # 如果对称轴介于0和99中间,且开头是向下的话,那么对称轴附近的比例值就是结果
    elif [ $(echo "$equ_a < 0" | bc) -eq 1 ];
    then
        best_rate+=( $(echo $extremeValue | cut -d '.' -f1) );
        amp_type=0
    # 如果对称轴介于0和99中间,且开头是向上的话,那么边界的比例值就是结果.
    else
        best_rate+=( $start_rate )
        best_rate+=( $end_rate )
        amp_type=-1
    fi
    # 3.2 对可能的取值做预测(推理) [也可以做Profiling(注释掉的代码部分)]
    best_incomes=()
    for rate in ${best_rate[@]}; 
    do
        income=( $(echo $rate $equ_a $equ_b $equ_c | awk '{ printf("%.10f", $2*$1*$1+$3*$1+$4 ); }') );
        # 如果推理出来的极值点恰好是Profiling时的点的话，那么直接用profiling的结果即可.
        for ((i=0;i<${#rate_array[@]};i++));
        do
            if [ ${rate_array[$i]} -eq $rate ]; then
                income=${time_array[$i]};
                break;
            fi
        done
        if [ $DEBUG_TYPE -eq 1 ];then
            echo "lnlamp: message: The predicted time benefit  is: ${income}s, when rate =${rate}. "
        fi
        best_incomes+=( $income )
        unset income
    done
    echo ""
    # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 



    # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 
    # Step4: 打印最终结果.
    # 设置是否有收益的边界为-1微秒
    bound_earnings=-0.000001
    # 如果是单调上升的情况
    if [ ${amp_type} -eq 2 ];
    then
        echo "Unfortunately, we did not find the most suitable mixed precision Rate for this program. So the original program is probably the best. "
        # 生成没有进行混合精度，但是PPCG优化后的代码提供给用户
        ppcg --target c --no-automatic-mixed-precision ${PPCG_ISL_FLAGS} ${PPCG_SCHEDULE_FLAGS} ${PPCG_TILE_FLAGS} ${PPCG_OPENMP_FLAGS} $src_args -o ${target_file} > /dev/null 2>&1
        if [ $? -ne 0 ]; then
            echo "lnlamp: error: PPCG Codegen meets errors at the end."
            echo "lnlamp: error: ppcg --target c --no-automatic-mixed-precision ${PPCG_ISL_FLAGS} ${PPCG_SCHEDULE_FLAGS} ${PPCG_TILE_FLAGS} ${PPCG_OPENMP_FLAGS} $src_args -o ${target_file}."
            exit
        fi
        echo "Now, We have automatically generated a program (${target_file}) with PPCG for you. "

        if [ $POLYBENCH_TEST_SWITCH -eq 1 ]; then
            # 临时加一个语句，生成schedule+mix的版本
            ppcg --target c --no-automatic-mixed-precision ${PPCG_ISL_FLAGS} ${PPCG_SCHEDULE_FLAGS} ${PPCG_OPENMP_FLAGS} $src_args -o ${target_file}.no-tile.c > /dev/null 2>&1
            # 临时加一个语句，生成只进行mix的版本
            ppcg --target c --no-automatic-mixed-precision --no-reschedule $src_args -o ${target_file}.only-mix.c > /dev/null 2>&1  
        fi
    # 如果是单调下降的情况
    elif [ ${amp_type} -eq 1 ];
    then
        echo "The performance of the lnlamp programs decreases monotonically with increasing Rate, so the Rate $start_rate is the best. "
        # 生成最合适比例下对应的混合精度代码提供给用户
        ppcg --target c -R ${best_rate[@]} ${PPCG_ISL_FLAGS} ${PPCG_SCHEDULE_FLAGS} ${PPCG_TILE_FLAGS} ${PPCG_OPENMP_FLAGS} $src_args -o ${target_file} > /dev/null 2>&1
        if [ $? -ne 0 ]; then
            echo "lnlamp: error: PPCG Codegen meets errors at the end."
            echo "lnlamp: error: The PPCG CMD is : ppcg --target c -R ${best_rate[@]} ${PPCG_ISL_FLAGS} ${PPCG_SCHEDULE_FLAGS} ${PPCG_TILE_FLAGS} ${PPCG_OPENMP_FLAGS} $src_args -o ${target_file}."
            exit
        fi
        echo "Now, We have automatically generated a mixed precision program (${target_file})at this Ratio(${best_rate[@]}). "
        FINAL_RESULT_READY=true

        if [ $POLYBENCH_TEST_SWITCH -eq 1 ]; then
            # 临时加一个语句，生成schedule+mix的版本
            ppcg --target c -R ${best_rate[@]} ${PPCG_ISL_FLAGS} ${PPCG_SCHEDULE_FLAGS} ${PPCG_OPENMP_FLAGS} $src_args -o ${target_file}.no-tile.c > /dev/null 2>&1
            # 临时加一个语句，生成只进行mix的版本
            ppcg --target c -R ${best_rate[@]} --no-reschedule $src_args -o ${target_file}.only-mix.c > /dev/null 2>&1
        fi
    # 如果是二次抛物线，开口向下的情况
    elif [ ${amp_type} -eq 0 ];
    then
        if [ $(echo "${best_incomes[@]} > ${bound_earnings}" | bc) -eq 1 ];
        then
            echo "The performance of the lnlamp program shows an open-down quadratic relationship with Rate, so the integer value around Rate($extremeValue) is probably the most appropriate ratio. "
            # 生成最合适比例下对应的混合精度代码提供给用户
            ppcg --target c -R ${best_rate[@]} ${PPCG_ISL_FLAGS} ${PPCG_SCHEDULE_FLAGS} ${PPCG_TILE_FLAGS} ${PPCG_OPENMP_FLAGS} $src_args -o ${target_file} > /dev/null 2>&1
            if [ $? -ne 0 ]; then
                echo "lnlamp: error: PPCG Codegen meets errors at the end."
                echo "lnlamp: error: The PPCG CMD is : ppcg --target c -R ${best_rate[@]} ${PPCG_ISL_FLAGS} ${PPCG_SCHEDULE_FLAGS} ${PPCG_TILE_FLAGS} ${PPCG_OPENMP_FLAGS} $src_args -o ${target_file}."
                exit
            fi
            echo "Now, We have automatically generated a mixed precision program (${target_file})at this Ratio(${best_rate[@]}). "
            FINAL_RESULT_READY=true

            if [ $POLYBENCH_TEST_SWITCH -eq 1 ]; then
                # 临时加一个语句，生成schedule+mix的版本
                ppcg --target c -R ${best_rate[@]} ${PPCG_ISL_FLAGS} ${PPCG_SCHEDULE_FLAGS} ${PPCG_OPENMP_FLAGS} $src_args -o ${target_file}.no-tile.c > /dev/null 2>&1
                # 临时加一个语句，生成只进行mix的版本
                ppcg --target c -R ${best_rate[@]} --no-reschedule $src_args -o ${target_file}.only-mix.c > /dev/null 2>&1
            fi
        else
            echo "Unfortunately, we did not find the most suitable mixed precision Rate for this program. So the original program is probably the best. "
            # 生成没有进行混合精度，但是PPCG优化后的代码提供给用户
            ppcg --target c --no-automatic-mixed-precision ${PPCG_ISL_FLAGS} ${PPCG_SCHEDULE_FLAGS} ${PPCG_TILE_FLAGS} ${PPCG_OPENMP_FLAGS} $src_args -o ${target_file} > /dev/null 2>&1
            if [ $? -ne 0 ]; then
                echo "lnlamp: error: PPCG Codegen meets errors at the end."
                echo "lnlamp: error: ppcg --target c --no-automatic-mixed-precision ${PPCG_ISL_FLAGS} ${PPCG_SCHEDULE_FLAGS} ${PPCG_TILE_FLAGS} ${PPCG_OPENMP_FLAGS} $src_args -o ${target_file}."
                exit
            fi
            echo "Now, We have automatically generated a program (${target_file}) with PPCG for you. "
            
            if [ $POLYBENCH_TEST_SWITCH -eq 1 ]; then
                # 临时加一个语句，生成schedule+mix的版本
                ppcg --target c --no-automatic-mixed-precision ${PPCG_ISL_FLAGS} ${PPCG_SCHEDULE_FLAGS} ${PPCG_OPENMP_FLAGS} $src_args -o ${target_file}.no-tile.c > /dev/null 2>&1
                # 临时加一个语句，生成只进行mix的版本
                ppcg --target c --no-automatic-mixed-precision --no-reschedule $src_args -o ${target_file}.only-mix.c > /dev/null 2>&1
            fi
        fi
    # 如果是二次抛物线，开口向上的情况
    elif [ ${amp_type} -eq -1 ];
    then
        max_income=-60
        max_income_id=-1.0
        # 确定一下最大收益及其对应的下标
        for ((i=0;i<${#best_incomes[@]};i++));
        do
            if [ $(echo "${best_incomes[$i]} > ${max_income}" | bc) -eq 1 ];
            then
                max_income=${best_incomes[$i]};
                max_income_id=$i;
            fi
        done
        # 根据最大收益,确定适不适合做混合精度
        if [ $(echo "${max_income} > ${bound_earnings}" | bc) -eq 1 ];
        then
            echo "The performance of the lnlamp program shows an open-upward quadratic curve relationship with Rate, so the integer value around Rate (${best_rate[$max_income_id]}) is probably the most appropriate ratio. "  
            # 生成最合适比例下对应的混合精度代码提供给用户
            ppcg --target c -R ${best_rate[$max_income_id]} ${PPCG_ISL_FLAGS} ${PPCG_SCHEDULE_FLAGS} ${PPCG_TILE_FLAGS} ${PPCG_OPENMP_FLAGS} $src_args -o ${target_file} > /dev/null 2>&1
            if [ $? -ne 0 ]; then
                echo "lnlamp: error: PPCG Codegen meets errors at the end."
                echo "lnlamp: error: ppcg --target c -R ${best_rate[$max_income_id]} ${PPCG_ISL_FLAGS} ${PPCG_SCHEDULE_FLAGS} ${PPCG_TILE_FLAGS} ${PPCG_OPENMP_FLAGS} $src_args -o ${target_file}."
                exit
            fi
            echo "Now, We have automatically generated a mixed precision program (${target_file})at this Ratio(${best_rate[$max_income_id]}). "
            FINAL_RESULT_READY=true

            if [ $POLYBENCH_TEST_SWITCH -eq 1 ]; then
                # 临时加一个语句，生成schedule+mix的版本
                ppcg --target c -R ${best_rate[$max_income_id]} ${PPCG_ISL_FLAGS} ${PPCG_SCHEDULE_FLAGS} ${PPCG_OPENMP_FLAGS} $src_args -o ${target_file}.no-tile.c > /dev/null 2>&1
                # 临时加一个语句，生成只进行mix的版本
                ppcg --target c -R ${best_rate[$max_income_id]} --no-reschedule $src_args -o ${target_file}.only-mix.c > /dev/null 2>&1
            fi
        else
            echo "Unfortunately, we did not find the most suitable mixed precision Rate for this program. So the original program is probably the best. "
            # 生成没有进行混合精度，但是PPCG优化后的代码提供给用户
            ppcg --target c --no-automatic-mixed-precision ${PPCG_ISL_FLAGS} ${PPCG_SCHEDULE_FLAGS} ${PPCG_TILE_FLAGS} ${PPCG_OPENMP_FLAGS} $src_args -o ${target_file} > /dev/null 2>&1
            if [ $? -ne 0 ]; then
                echo "lnlamp: error: PPCG Codegen meets errors at the end."
                echo "lnlamp: error: ppcg --target c --no-automatic-mixed-precision ${PPCG_ISL_FLAGS} ${PPCG_SCHEDULE_FLAGS} ${PPCG_TILE_FLAGS} ${PPCG_OPENMP_FLAGS} $src_args -o ${target_file}."
                exit
            fi
            echo "Now, We have automatically generated a program (${target_file}) with PPCG for you. "
            
            if [ $POLYBENCH_TEST_SWITCH -eq 1 ]; then
                # 临时加一个语句，生成schedule+mix的版本
                ppcg --target c --no-automatic-mixed-precision ${PPCG_ISL_FLAGS} ${PPCG_SCHEDULE_FLAGS} ${PPCG_OPENMP_FLAGS} $src_args -o ${target_file}.no-tile.c > /dev/null 2>&1
                # 临时加一个语句，生成只进行mix的版本
                ppcg --target c --no-automatic-mixed-precision --no-reschedule $src_args -o ${target_file}.only-mix.c > /dev/null 2>&1
            fi
        fi
    else
        echo "lnlamp: error: There was a problem printing the final results, please contact the program developer! "
    fi
    end=`date +%s%N`
    time_inference=$((($end-$start)/1000000)) # 毫秒

    if [ $POLYBENCH_TEST_SWITCH -eq 1 ]; then
        # 最后生成PPCG进行调度优化之后的原始精度的代码（默认tile,以及no-tile），以方便做实验时进行对比（注意该部分只是为了实验测试方便而已）。
        ppcg --target c --no-automatic-mixed-precision ${PPCG_ISL_FLAGS} ${PPCG_SCHEDULE_FLAGS} ${PPCG_TILE_FLAGS} ${PPCG_OPENMP_FLAGS} $src_args -o ${src_args}.ppcg.c > /dev/null 2>&1
        ppcg --target c --no-automatic-mixed-precision ${PPCG_ISL_FLAGS} ${PPCG_SCHEDULE_FLAGS} ${PPCG_OPENMP_FLAGS} $src_args -o ${src_args}.ppcg.no-tile.c > /dev/null 2>&1
    fi
    # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 
fi


# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 
# Step5: 验证结果程序的误差情况.
# 
if [[ ${FINAL_RESULT_READY} = true ]] ; then
    # 使用 date +%s%N 可以获得一个纳秒级的unix时间戳(当前时间), 进行计时
    start=`date +%s%N`

    # 如果指定了rate_array，那么误差模型不会获取double的结果，需要在这里编译和执行并获取double的误差情况.
    if [ $specify_rate_array_flag -gt 1 ];
    then
        ppcg --target c --no-automatic-mixed-precision ${PPCG_ISL_FLAGS} ${PPCG_SCHEDULE_FLAGS} ${PPCG_TILE_FLAGS} ${PPCG_OPENMP_FLAGS} $src_args -o ____lnlamp_ppcg__${prf_suf} > /dev/null 2>&1
        if [ $? -ne 0 ]; then
            echo "lnlamp: error: PPCG Codegen meets errors."
            echo "lnlamp: error: The PPCG CMD is : ppcg --target c --no-automatic-mixed-precision ${PPCG_ISL_FLAGS} ${PPCG_SCHEDULE_FLAGS} ${PPCG_TILE_FLAGS} ${PPCG_OPENMP_FLAGS} $src_args -o ____lnlamp_ppcg__${prf_suf} "
            exit
        fi
        ${VERBOSE} ${CC} ${CFLAGS} ${LIB_FLAGS} ${PROFILER_FLAGS} ____lnlamp_ppcg__${prf_suf} -o  ____lnlamp_ppcg_double__.exe ${EXIT_FLAGS} > /dev/null 2>&1
        if [ $? -ne 0 ]; then
            echo "lnlamp: error: Compiling meets errors."
            echo "lnlamp: error: The compiler CMD is : ${VERBOSE} ${CC} ${CFLAGS} ${LIB_FLAGS} ${PROFILER_FLAGS} -DDATA_TYPE_IS_DOUBLE=1 ____lnlamp_ppcg__${prf_suf} -o  ____lnlamp_ppcg_double__.exe ${EXIT_FLAGS}"
            exit
        fi
        rm -f ____lnlamp_ppcg__${prf_suf}

        # 执行程序，获取计算结果
        if [ -e $input ];
        then
            { ./____lnlamp_ppcg_double__.exe < $input 2> ____lnlamp_error_double.res > /dev/null; } 2> /dev/null
        else
            { ./____lnlamp_ppcg_double__.exe  2> ____lnlamp_error_double.res > /dev/null; } 2> /dev/null
        fi
        rm -f ____lnlamp_ppcg_double__.exe

        # 删除非计算结果的那些字符串
        sed -i "/==BEGIN DUMP_ARRAYS==/d"  ____lnlamp_error_double.res
        sed -i "/==END   DUMP_ARRAYS==/d"  ____lnlamp_error_double.res
        sed -i "/begin dump/d"             ____lnlamp_error_double.res 
        sed -i "/end   dump/d"             ____lnlamp_error_double.res
    fi

    # 并行地编译amp最终的代码
    ${VERBOSE} ${CC} ${CFLAGS} ${LIB_FLAGS} ${PROFILER_FLAGS} ${target_file} -o  ____lnlamp_amp_final_res__.exe ${EXIT_FLAGS} > /dev/null 2>&1
    if [ $? -ne 0 ]; then
        echo "lnlamp: error: Compiling meets errors."
        echo "lnlamp: error: The compiler CMD is : ${VERBOSE} ${CC} ${CFLAGS} ${LIB_FLAGS} ${PROFILER_FLAGS} ${target_file} -o  ____lnlamp_amp_final_res__.exe ${EXIT_FLAGS}"
        exit
    fi
    
    # 执行amp最终程序，获取其计算结果
    if [ -e $input ];
    then
        { ./____lnlamp_amp_final_res__.exe  < $input 2> ____lnlamp_error_amp_final__.res  > /dev/null; } 2> /dev/null
    else
        { ./____lnlamp_amp_final_res__.exe           2> ____lnlamp_error_amp_final__.res  > /dev/null; } 2> /dev/null
    fi
    rm -f ____lnlamp_amp_final_res__.exe

    # 删除非计算结果的那些字符串
    sed -i "/==BEGIN DUMP_ARRAYS==/d"  ____lnlamp_error_amp_final__.res
    sed -i "/==END   DUMP_ARRAYS==/d"  ____lnlamp_error_amp_final__.res
    sed -i "/begin dump/d"             ____lnlamp_error_amp_final__.res 
    sed -i "/end   dump/d"             ____lnlamp_error_amp_final__.res
    
    #如果double的结果文件不存在，则直接退出程序
    if [ ! -e "____lnlamp_error_double.res" ]; then
        echo "lnlamp: error: Can't calculate the final error result, because lnlamp_error_double.res is not exist!!!"
    fi
    # 计算误差结果
    python3 $lnlamp_dir/lnlamp_internal_calculate_errors.py ____lnlamp_error_double.res ____lnlamp_error_amp_final__.res > ____lnlamp_amp_final_error_temp_use.log 2>&1 ;
    if [ $? -ne 0 ]; then
        echo "lnlamp: error: Calculate errors(lnlamp_internal_calculate_errors.py) problems encountered!"
        exit
    fi
    rm -f ____lnlamp_error_double.res ____lnlamp_error_amp_final__.res

    # 获取各种误差数据
    dbl_no=`cat ____lnlamp_amp_final_error_temp_use.log | head -n 1`;
    amp_no=`cat ____lnlamp_amp_final_error_temp_use.log | head -n 2 | tail -n 1`;
    mean_err_prc=`cat ____lnlamp_amp_final_error_temp_use.log | head -n 3 | tail -n 1`;
    mean_err_abs=`cat ____lnlamp_amp_final_error_temp_use.log | head -n 4 | tail -n 1`;
    max_err_prc=`cat ____lnlamp_amp_final_error_temp_use.log | head -n 5 | tail -n 1`;
    max_err_abs=`cat ____lnlamp_amp_final_error_temp_use.log | head -n 6 | tail -n 1`;
    rm -f ____lnlamp_amp_final_error_temp_use.log

    # 根据类型确定最终结果的误差值
    # 如果有非数，先不进行处理
    if [ $ERROR_TYPE -eq 1 ]; then
        amp_err=$max_err_abs
    elif [ $ERROR_TYPE -eq 2 ]; then
        amp_err=$max_err_prc
    elif [ $ERROR_TYPE -eq 3 ]; then
        amp_err=$mean_err_abs
    elif [ $ERROR_TYPE -eq 4 ]; then
        amp_err=$mean_err_prc
    else
        echo "lnlamp: error: ERROR_TYPE configuration errors!"
        exit
    fi
    unset dbl_no
    unset amp_no
    unset mean_err_prc
    unset mean_err_abs
    unset max_err_prc
    unset max_err_abs
    
    # 如果amp_err 大于 误差阈值，那么说明该结果的误差不符合要求。
    if [ $(echo "$amp_err > $ERROR_THRESHOLD" | bc) -eq 1 ];
    then
        echo "lnlamp: error: The error of ${target_file} exceeds the error threshold($amp_err > $ERROR_THRESHOLD)!!!"
        rm -f ${target_file}
        exit
    else
        echo "The error of ${target_file} is $amp_err."
    fi

    # 结束计时
    end=`date +%s%N`
    time_verify=$((($end-$start)/1000000)) # 毫秒
fi
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 
echo ""

# 打印耗时情况
if [ $DEBUG_TYPE -eq 1 ];then
    echo "lnlamp: message: The error caluting timeConsuming is: ${time_error}ms, the profiling timeConsuming is: ${time_profiling}ms,  the inference timeConsuming is: ${time_inference}ms, the result verify time is: ${time_verify}ms. "
    echo ""
fi
